Compare commits
12 Commits
6f9b384caa
...
cbde498ae8
| Author | SHA1 | Date | |
|---|---|---|---|
| cbde498ae8 | |||
| 9feace9558 | |||
| 2a5496118b | |||
| f362b2ab77 | |||
| 7a8cd490d5 | |||
| 5a20d97084 | |||
| 8def0af08f | |||
| 348d8e1d03 | |||
| a078503a89 | |||
| bc57914131 | |||
| 3b01625f7d | |||
| 8cf4762a65 |
@@ -3,7 +3,7 @@
|
|||||||
- get age key from SSH
|
- get age key from SSH
|
||||||
```console
|
```console
|
||||||
curl https://raw.githubusercontent.com/elitak/nixos-infect/master/nixos-infect | PROVIDER=hetznercloud NIX_CHANNEL=nixos-24.05 bash 2>&1 | tee /tmp/infect.log
|
curl https://raw.githubusercontent.com/elitak/nixos-infect/master/nixos-infect | PROVIDER=hetznercloud NIX_CHANNEL=nixos-24.05 bash 2>&1 | tee /tmp/infect.log
|
||||||
nix-shell -p ssh-to-age --run 'ssh-keyscan example.com | ssh-to-age'
|
nix-shell -p ssh-to-age --run 'ssh-keyscan install.cloonar.com | ssh-to-age'
|
||||||
```
|
```
|
||||||
- fix secrets files
|
- fix secrets files
|
||||||
```console
|
```console
|
||||||
|
|||||||
340
esphome/hallway-light-switch.yaml
Normal file
340
esphome/hallway-light-switch.yaml
Normal file
@@ -0,0 +1,340 @@
|
|||||||
|
substitutions:
|
||||||
|
# Default name
|
||||||
|
name: "hallway-light-switch"
|
||||||
|
# Default friendly name
|
||||||
|
friendly_name: "Hallway Light Switch"
|
||||||
|
# Allows ESP device to be automatically linked to an 'Area' in Home Assistant. Typically used for areas such as 'Lounge Room', 'Kitchen' etc
|
||||||
|
room: "Hallway"
|
||||||
|
# Description as appears in ESPHome & top of webserver page
|
||||||
|
device_description: "Hallway Light Switch"
|
||||||
|
# Project Name
|
||||||
|
project_name: "Athom Technology.Mini Relay V2"
|
||||||
|
# Projection version denotes the release version of the yaml file, allowing checking of deployed vs latest version
|
||||||
|
project_version: "v2.0.4"
|
||||||
|
# Restore the relay (GPO switch) upon reboot to state:
|
||||||
|
light_restore_mode: RESTORE_DEFAULT_OFF
|
||||||
|
# Set the update interval for sensors
|
||||||
|
sensor_update_interval: 10s
|
||||||
|
# Current Limit in Amps.
|
||||||
|
current_limit : "10"
|
||||||
|
# Define a domain for this device to use. i.e. iot.home.lan (so device will appear as athom-smart-plug-v2.iot.home.lan in DNS/DHCP logs)
|
||||||
|
dns_domain: ".cloonar.smart"
|
||||||
|
# Set timezone of the smart plug. Useful if the plug is in a location different to the HA server. Can be entered in unix Country/Area format (i.e. "Australia/Sydney")
|
||||||
|
timezone: ""
|
||||||
|
# Set the duration between the sntp service polling ntp.org servers for an update
|
||||||
|
sntp_update_interval: 6h
|
||||||
|
# Network time servers for your region, enter from lowest to highest priority. To use local servers update as per zones or countries at: https://www.ntppool.org/zone/@
|
||||||
|
sntp_server_1: "0.pool.ntp.org"
|
||||||
|
sntp_server_2: "1.pool.ntp.org"
|
||||||
|
sntp_server_3: "2.pool.ntp.org"
|
||||||
|
# Enables faster network connections, with last connected SSID being connected to and no full scan for SSID being undertaken
|
||||||
|
wifi_fast_connect: "false"
|
||||||
|
# Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE
|
||||||
|
log_level: "WARN"
|
||||||
|
# Hide the ENERGY sensor that shows kWh consumed, but with no time period associated with it. Resets when device restarted and reflashed.
|
||||||
|
hide_energy_sensor: "true"
|
||||||
|
# Enable or disable the use of IPv6 networking on the device
|
||||||
|
ipv6_enable: "false"
|
||||||
|
|
||||||
|
esphome:
|
||||||
|
name: "${name}"
|
||||||
|
friendly_name: "${friendly_name}"
|
||||||
|
comment: "${device_description}"
|
||||||
|
area: "${room}"
|
||||||
|
name_add_mac_suffix: false
|
||||||
|
min_version: 2024.5.0
|
||||||
|
project:
|
||||||
|
name: "${project_name}"
|
||||||
|
version: "${project_version}"
|
||||||
|
platformio_options:
|
||||||
|
board_build.mcu: esp32c3
|
||||||
|
board_build.variant: esp32c3
|
||||||
|
board_build.flash_mode: dio
|
||||||
|
|
||||||
|
esp32:
|
||||||
|
board: esp32-c3-devkitm-1
|
||||||
|
flash_size: 4MB
|
||||||
|
variant: ESP32C3
|
||||||
|
framework:
|
||||||
|
type: arduino
|
||||||
|
version: recommended
|
||||||
|
|
||||||
|
preferences:
|
||||||
|
flash_write_interval: 5min
|
||||||
|
|
||||||
|
api:
|
||||||
|
|
||||||
|
ota:
|
||||||
|
- platform: esphome
|
||||||
|
|
||||||
|
mdns:
|
||||||
|
disabled: false
|
||||||
|
|
||||||
|
web_server:
|
||||||
|
port: 80
|
||||||
|
|
||||||
|
network:
|
||||||
|
enable_ipv6: ${ipv6_enable}
|
||||||
|
|
||||||
|
wifi:
|
||||||
|
ssid: !secret wifi_ssid
|
||||||
|
password: !secret wifi_password
|
||||||
|
fast_connect: True
|
||||||
|
domain: ${dns_domain}
|
||||||
|
|
||||||
|
esp32_improv:
|
||||||
|
authorizer: none
|
||||||
|
|
||||||
|
uart:
|
||||||
|
rx_pin: GPIO20
|
||||||
|
baud_rate: 4800
|
||||||
|
data_bits: 8
|
||||||
|
stop_bits: 1
|
||||||
|
parity: EVEN
|
||||||
|
|
||||||
|
globals:
|
||||||
|
- id: total_energy
|
||||||
|
type: float
|
||||||
|
restore_value: yes
|
||||||
|
initial_value: '0.0'
|
||||||
|
|
||||||
|
binary_sensor:
|
||||||
|
- platform: status
|
||||||
|
name: "Status"
|
||||||
|
entity_category: diagnostic
|
||||||
|
|
||||||
|
- platform: gpio
|
||||||
|
pin:
|
||||||
|
number: GPIO3
|
||||||
|
mode: INPUT_PULLUP
|
||||||
|
inverted: true
|
||||||
|
name: "Power Button"
|
||||||
|
disabled_by_default: true
|
||||||
|
on_multi_click:
|
||||||
|
- timing:
|
||||||
|
- ON for at most 1s
|
||||||
|
- OFF for at least 0.2s
|
||||||
|
then:
|
||||||
|
- light.toggle: mini_relay
|
||||||
|
- timing:
|
||||||
|
- ON for at least 4s
|
||||||
|
then:
|
||||||
|
- button.press: Reset
|
||||||
|
|
||||||
|
- platform: gpio
|
||||||
|
id: the_switch
|
||||||
|
name: "Power Switch"
|
||||||
|
pin:
|
||||||
|
number: GPIO4
|
||||||
|
mode: INPUT_PULLUP
|
||||||
|
inverted: true
|
||||||
|
on_multi_click:
|
||||||
|
- timing:
|
||||||
|
- ON for at most 1s
|
||||||
|
then:
|
||||||
|
- light.toggle: mini_relay
|
||||||
|
|
||||||
|
sensor:
|
||||||
|
- platform: uptime
|
||||||
|
name: "Uptime Sensor"
|
||||||
|
id: uptime_sensor
|
||||||
|
entity_category: diagnostic
|
||||||
|
internal: true
|
||||||
|
|
||||||
|
- platform: wifi_signal
|
||||||
|
name: "WiFi Signal dB"
|
||||||
|
id: wifi_signal_db
|
||||||
|
update_interval: 60s
|
||||||
|
entity_category: "diagnostic"
|
||||||
|
|
||||||
|
- platform: copy
|
||||||
|
source_id: wifi_signal_db
|
||||||
|
name: "WiFi Signal Percent"
|
||||||
|
filters:
|
||||||
|
- lambda: return min(max(2 * (x + 100.0), 0.0), 100.0);
|
||||||
|
unit_of_measurement: "Signal %"
|
||||||
|
entity_category: "diagnostic"
|
||||||
|
device_class: ""
|
||||||
|
|
||||||
|
- platform: cse7766
|
||||||
|
id: athom_cse7766
|
||||||
|
current:
|
||||||
|
name: "Current"
|
||||||
|
filters:
|
||||||
|
- throttle_average: ${sensor_update_interval}
|
||||||
|
- lambda: if (x < 0.060) return 0.0; else return x; #For the chip will report less than 3w power when no load is connected
|
||||||
|
on_value_range:
|
||||||
|
- above: ${current_limit}
|
||||||
|
then:
|
||||||
|
- light.turn_off: mini_relay
|
||||||
|
|
||||||
|
voltage:
|
||||||
|
name: "Voltage"
|
||||||
|
filters:
|
||||||
|
- throttle_average: ${sensor_update_interval}
|
||||||
|
|
||||||
|
power:
|
||||||
|
name: "Power"
|
||||||
|
id: power_sensor
|
||||||
|
filters:
|
||||||
|
- throttle_average: ${sensor_update_interval}
|
||||||
|
- lambda: if (x < 3.0) return 0.0; else return x; #For the chip will report less than 3w power when no load is connected
|
||||||
|
|
||||||
|
energy:
|
||||||
|
name: "Energy"
|
||||||
|
id: energy
|
||||||
|
unit_of_measurement: kWh
|
||||||
|
filters:
|
||||||
|
- throttle: ${sensor_update_interval}
|
||||||
|
# Multiplication factor from W to kW is 0.001
|
||||||
|
- multiply: 0.001
|
||||||
|
on_value:
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
static float previous_energy_value = 0.0;
|
||||||
|
float current_energy_value = id(energy).state;
|
||||||
|
id(total_energy) += current_energy_value - previous_energy_value;
|
||||||
|
previous_energy_value = current_energy_value;
|
||||||
|
id(total_energy_sensor).update();
|
||||||
|
|
||||||
|
apparent_power:
|
||||||
|
name: "Apparent Power"
|
||||||
|
filters:
|
||||||
|
- throttle_average: ${sensor_update_interval}
|
||||||
|
reactive_power:
|
||||||
|
name: "Reactive Power"
|
||||||
|
filters:
|
||||||
|
- throttle_average: ${sensor_update_interval}
|
||||||
|
power_factor:
|
||||||
|
name: "Power Factor"
|
||||||
|
filters:
|
||||||
|
- throttle_average: ${sensor_update_interval}
|
||||||
|
|
||||||
|
- platform: template
|
||||||
|
name: "Total Energy"
|
||||||
|
id: total_energy_sensor
|
||||||
|
unit_of_measurement: kWh
|
||||||
|
device_class: "energy"
|
||||||
|
state_class: "total_increasing"
|
||||||
|
icon: "mdi:lightning-bolt"
|
||||||
|
accuracy_decimals: 3
|
||||||
|
lambda: |-
|
||||||
|
return id(total_energy);
|
||||||
|
update_interval: ${sensor_update_interval}
|
||||||
|
|
||||||
|
- platform: total_daily_energy
|
||||||
|
name: "Total Energy Today"
|
||||||
|
restore: true
|
||||||
|
power_id: power_sensor
|
||||||
|
unit_of_measurement: kWh
|
||||||
|
accuracy_decimals: 3
|
||||||
|
filters:
|
||||||
|
- multiply: 0.001
|
||||||
|
|
||||||
|
button:
|
||||||
|
- platform: restart
|
||||||
|
name: "Restart"
|
||||||
|
entity_category: config
|
||||||
|
|
||||||
|
- platform: factory_reset
|
||||||
|
name: "Factory Reset"
|
||||||
|
id: Reset
|
||||||
|
entity_category: config
|
||||||
|
|
||||||
|
- platform: safe_mode
|
||||||
|
name: "Safe Mode"
|
||||||
|
internal: false
|
||||||
|
entity_category: config
|
||||||
|
|
||||||
|
output:
|
||||||
|
- platform: gpio
|
||||||
|
id: relay_output
|
||||||
|
pin: GPIO6
|
||||||
|
|
||||||
|
light:
|
||||||
|
- platform: status_led
|
||||||
|
id: led
|
||||||
|
name: "Blue LED"
|
||||||
|
disabled_by_default: true
|
||||||
|
pin:
|
||||||
|
number: GPIO7
|
||||||
|
inverted: true
|
||||||
|
|
||||||
|
- platform: binary
|
||||||
|
id: mini_relay
|
||||||
|
output: relay_output
|
||||||
|
name: "Mini Switch"
|
||||||
|
restore_mode: ${light_restore_mode}
|
||||||
|
on_turn_on:
|
||||||
|
- light.turn_on: led
|
||||||
|
on_turn_off:
|
||||||
|
- light.turn_off: led
|
||||||
|
|
||||||
|
text_sensor:
|
||||||
|
- platform: wifi_info
|
||||||
|
ip_address:
|
||||||
|
name: "IP Address"
|
||||||
|
entity_category: diagnostic
|
||||||
|
ssid:
|
||||||
|
name: "Connected SSID"
|
||||||
|
entity_category: diagnostic
|
||||||
|
mac_address:
|
||||||
|
name: "Mac Address"
|
||||||
|
entity_category: diagnostic
|
||||||
|
|
||||||
|
# Creates a sensor showing when the device was last restarted
|
||||||
|
- platform: template
|
||||||
|
name: 'Last Restart'
|
||||||
|
id: device_last_restart
|
||||||
|
icon: mdi:clock
|
||||||
|
entity_category: diagnostic
|
||||||
|
# device_class: timestamp
|
||||||
|
|
||||||
|
# Creates a sensor of the uptime of the device, in formatted days, hours, minutes and seconds
|
||||||
|
- platform: template
|
||||||
|
name: "Uptime"
|
||||||
|
entity_category: diagnostic
|
||||||
|
lambda: |-
|
||||||
|
int seconds = (id(uptime_sensor).state);
|
||||||
|
int days = seconds / (24 * 3600);
|
||||||
|
seconds = seconds % (24 * 3600);
|
||||||
|
int hours = seconds / 3600;
|
||||||
|
seconds = seconds % 3600;
|
||||||
|
int minutes = seconds / 60;
|
||||||
|
seconds = seconds % 60;
|
||||||
|
if ( days > 3650 ) {
|
||||||
|
return { "Starting up" };
|
||||||
|
} else if ( days ) {
|
||||||
|
return { (String(days) +"d " + String(hours) +"h " + String(minutes) +"m "+ String(seconds) +"s").c_str() };
|
||||||
|
} else if ( hours ) {
|
||||||
|
return { (String(hours) +"h " + String(minutes) +"m "+ String(seconds) +"s").c_str() };
|
||||||
|
} else if ( minutes ) {
|
||||||
|
return { (String(minutes) +"m "+ String(seconds) +"s").c_str() };
|
||||||
|
} else {
|
||||||
|
return { (String(seconds) +"s").c_str() };
|
||||||
|
}
|
||||||
|
icon: mdi:clock-start
|
||||||
|
|
||||||
|
time:
|
||||||
|
- platform: sntp
|
||||||
|
id: sntp_time
|
||||||
|
# Define the timezone of the device
|
||||||
|
timezone: "${timezone}"
|
||||||
|
# Change sync interval from default 5min to 6 hours (or as set in substitutions)
|
||||||
|
update_interval: ${sntp_update_interval}
|
||||||
|
# Set specific sntp servers to use
|
||||||
|
servers:
|
||||||
|
- "${sntp_server_1}"
|
||||||
|
- "${sntp_server_2}"
|
||||||
|
- "${sntp_server_3}"
|
||||||
|
# Publish the time the device was last restarted
|
||||||
|
on_time_sync:
|
||||||
|
then:
|
||||||
|
# Update last restart time, but only once.
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
lambda: 'return id(device_last_restart).state == "";'
|
||||||
|
then:
|
||||||
|
- text_sensor.template.publish:
|
||||||
|
id: device_last_restart
|
||||||
|
state: !lambda 'return id(sntp_time).now().strftime("%a %d %b %Y - %I:%M:%S %p");'
|
||||||
@@ -10,7 +10,6 @@ substitutions:
|
|||||||
sntp_server_1: "0.pool.ntp.org"
|
sntp_server_1: "0.pool.ntp.org"
|
||||||
sntp_server_2: "1.pool.ntp.org"
|
sntp_server_2: "1.pool.ntp.org"
|
||||||
sntp_server_3: "2.pool.ntp.org"
|
sntp_server_3: "2.pool.ntp.org"
|
||||||
log_level: "WARN"
|
|
||||||
|
|
||||||
esphome:
|
esphome:
|
||||||
name: "${name}"
|
name: "${name}"
|
||||||
@@ -23,27 +22,27 @@ esphome:
|
|||||||
name: "${project_name}"
|
name: "${project_name}"
|
||||||
version: "${project_version}"
|
version: "${project_version}"
|
||||||
on_boot:
|
on_boot:
|
||||||
then:
|
then:
|
||||||
- light.turn_on:
|
- light.turn_on:
|
||||||
id: rgbww_light
|
id: rgbww_light
|
||||||
- delay: 100ms
|
- delay: 100ms
|
||||||
- light.turn_on:
|
- light.turn_on:
|
||||||
id: rgbww_light
|
id: rgbww_light
|
||||||
brightness: 20%
|
brightness: 20%
|
||||||
- delay: 100ms
|
- delay: 100ms
|
||||||
- light.turn_on:
|
- light.turn_on:
|
||||||
id: rgbww_light
|
id: rgbww_light
|
||||||
red: 100%
|
red: 100%
|
||||||
green: 50%
|
green: 50%
|
||||||
blue: 0%
|
blue: 0%
|
||||||
white: 100%
|
white: 100%
|
||||||
|
|
||||||
interval:
|
interval:
|
||||||
- interval: 15s
|
- interval: 15s
|
||||||
then:
|
then:
|
||||||
- if:
|
- if:
|
||||||
condition:
|
condition:
|
||||||
api.connected: # check if api connected
|
api.connected:
|
||||||
else:
|
else:
|
||||||
- light.turn_on:
|
- light.turn_on:
|
||||||
id: rgbww_light
|
id: rgbww_light
|
||||||
@@ -61,21 +60,31 @@ api:
|
|||||||
ota:
|
ota:
|
||||||
- platform: esphome
|
- platform: esphome
|
||||||
|
|
||||||
logger:
|
|
||||||
|
|
||||||
mdns:
|
|
||||||
disabled: false
|
|
||||||
|
|
||||||
wifi:
|
wifi:
|
||||||
ssid: !secret wifi_ssid
|
# Disable fast_connect so we do a full scan (required for hidden SSIDs)
|
||||||
password: !secret wifi_password
|
fast_connect: false
|
||||||
fast_connect: True
|
domain: "${dns_domain}"
|
||||||
domain: .cloonar.smart
|
|
||||||
|
|
||||||
captive_portal:
|
# Your hidden network
|
||||||
|
networks:
|
||||||
|
- ssid: !secret wifi_ssid
|
||||||
|
password: !secret wifi_password
|
||||||
|
channel: 1
|
||||||
|
hidden: true
|
||||||
|
|
||||||
dashboard_import:
|
manual_ip:
|
||||||
package_import_url: github://athom-tech/athom-configs/athom-rgbww-light.yaml
|
static_ip: 10.42.100.11
|
||||||
|
gateway: 10.42.100.1
|
||||||
|
subnet: 255.255.255.0
|
||||||
|
dns1: 8.8.8.8
|
||||||
|
dns2: 1.1.1.1
|
||||||
|
|
||||||
|
# Fallback access point if Wi-Fi fails
|
||||||
|
ap:
|
||||||
|
ssid: "${name}_AP"
|
||||||
|
password: "bulb_fallback_pw"
|
||||||
|
ap_timeout: 2min # after 2 min of failed join, enable AP
|
||||||
|
reboot_timeout: 5min # if still not joined after 5 min, reboot and retry
|
||||||
|
|
||||||
binary_sensor:
|
binary_sensor:
|
||||||
- platform: status
|
- platform: status
|
||||||
@@ -93,7 +102,7 @@ sensor:
|
|||||||
name: "WiFi Signal dB"
|
name: "WiFi Signal dB"
|
||||||
id: wifi_signal_db
|
id: wifi_signal_db
|
||||||
update_interval: 60s
|
update_interval: 60s
|
||||||
entity_category: "diagnostic"
|
entity_category: diagnostic
|
||||||
|
|
||||||
- platform: copy
|
- platform: copy
|
||||||
source_id: wifi_signal_db
|
source_id: wifi_signal_db
|
||||||
@@ -101,23 +110,7 @@ sensor:
|
|||||||
filters:
|
filters:
|
||||||
- lambda: return min(max(2 * (x + 100.0), 0.0), 100.0);
|
- lambda: return min(max(2 * (x + 100.0), 0.0), 100.0);
|
||||||
unit_of_measurement: "Signal %"
|
unit_of_measurement: "Signal %"
|
||||||
entity_category: "diagnostic"
|
entity_category: diagnostic
|
||||||
device_class: ""
|
|
||||||
|
|
||||||
button:
|
|
||||||
- platform: restart
|
|
||||||
name: "Restart"
|
|
||||||
entity_category: config
|
|
||||||
|
|
||||||
- platform: factory_reset
|
|
||||||
name: "Factory Reset"
|
|
||||||
id: Reset
|
|
||||||
entity_category: config
|
|
||||||
|
|
||||||
- platform: safe_mode
|
|
||||||
name: "Safe Mode"
|
|
||||||
internal: false
|
|
||||||
entity_category: config
|
|
||||||
|
|
||||||
output:
|
output:
|
||||||
- platform: esp8266_pwm
|
- platform: esp8266_pwm
|
||||||
@@ -171,55 +164,47 @@ text_sensor:
|
|||||||
name: "Mac Address"
|
name: "Mac Address"
|
||||||
entity_category: diagnostic
|
entity_category: diagnostic
|
||||||
|
|
||||||
# Creates a sensor showing when the device was last restarted
|
|
||||||
- platform: template
|
- platform: template
|
||||||
name: 'Last Restart'
|
name: 'Last Restart'
|
||||||
id: device_last_restart
|
id: device_last_restart
|
||||||
icon: mdi:clock
|
icon: mdi:clock
|
||||||
entity_category: diagnostic
|
entity_category: diagnostic
|
||||||
# device_class: timestamp
|
|
||||||
|
|
||||||
# Creates a sensor of the uptime of the device, in formatted days, hours, minutes and seconds
|
|
||||||
- platform: template
|
- platform: template
|
||||||
name: "Uptime"
|
name: "Uptime"
|
||||||
entity_category: diagnostic
|
entity_category: diagnostic
|
||||||
lambda: |-
|
lambda: |-
|
||||||
int seconds = (id(uptime_sensor).state);
|
int seconds = (id(uptime_sensor).state);
|
||||||
int days = seconds / (24 * 3600);
|
int days = seconds / (24 * 3600);
|
||||||
seconds = seconds % (24 * 3600);
|
seconds %= (24 * 3600);
|
||||||
int hours = seconds / 3600;
|
int hours = seconds / 3600;
|
||||||
seconds = seconds % 3600;
|
seconds %= 3600;
|
||||||
int minutes = seconds / 60;
|
int minutes = seconds / 60;
|
||||||
seconds = seconds % 60;
|
seconds %= 60;
|
||||||
if ( days > 3650 ) {
|
if (days > 3650) {
|
||||||
return { "Starting up" };
|
return { "Starting up" };
|
||||||
} else if ( days ) {
|
} else if (days) {
|
||||||
return { (String(days) +"d " + String(hours) +"h " + String(minutes) +"m "+ String(seconds) +"s").c_str() };
|
return { (String(days) + "d " + String(hours) + "h " + String(minutes) + "m " + String(seconds) + "s").c_str() };
|
||||||
} else if ( hours ) {
|
} else if (hours) {
|
||||||
return { (String(hours) +"h " + String(minutes) +"m "+ String(seconds) +"s").c_str() };
|
return { (String(hours) + "h " + String(minutes) + "m " + String(seconds) + "s").c_str() };
|
||||||
} else if ( minutes ) {
|
} else if (minutes) {
|
||||||
return { (String(minutes) +"m "+ String(seconds) +"s").c_str() };
|
return { (String(minutes) + "m " + String(seconds) + "s").c_str() };
|
||||||
} else {
|
} else {
|
||||||
return { (String(seconds) +"s").c_str() };
|
return { (String(seconds) + "s").c_str() };
|
||||||
}
|
}
|
||||||
icon: mdi:clock-start
|
icon: mdi:clock-start
|
||||||
|
|
||||||
time:
|
time:
|
||||||
- platform: sntp
|
- platform: sntp
|
||||||
id: sntp_time
|
id: sntp_time
|
||||||
# Define the timezone of the device
|
|
||||||
timezone: "${timezone}"
|
timezone: "${timezone}"
|
||||||
# Change sync interval from default 5min to 6 hours (or as set in substitutions)
|
|
||||||
update_interval: ${sntp_update_interval}
|
update_interval: ${sntp_update_interval}
|
||||||
# Set specific sntp servers to use
|
|
||||||
servers:
|
servers:
|
||||||
- "${sntp_server_1}"
|
- "${sntp_server_1}"
|
||||||
- "${sntp_server_2}"
|
- "${sntp_server_2}"
|
||||||
- "${sntp_server_3}"
|
- "${sntp_server_3}"
|
||||||
# Publish the time the device was last restarted
|
|
||||||
on_time_sync:
|
on_time_sync:
|
||||||
then:
|
then:
|
||||||
# Update last restart time, but only once.
|
|
||||||
- if:
|
- if:
|
||||||
condition:
|
condition:
|
||||||
lambda: 'return id(device_last_restart).state == "";'
|
lambda: 'return id(device_last_restart).state == "";'
|
||||||
|
|||||||
@@ -61,21 +61,18 @@ api:
|
|||||||
ota:
|
ota:
|
||||||
- platform: esphome
|
- platform: esphome
|
||||||
|
|
||||||
logger:
|
|
||||||
|
|
||||||
mdns:
|
|
||||||
disabled: false
|
|
||||||
|
|
||||||
wifi:
|
wifi:
|
||||||
ssid: !secret wifi_ssid
|
|
||||||
password: !secret wifi_password
|
|
||||||
fast_connect: True
|
|
||||||
domain: .cloonar.smart
|
domain: .cloonar.smart
|
||||||
|
fast_connect: False
|
||||||
captive_portal:
|
networks:
|
||||||
|
- ssid: !secret wifi_ssid
|
||||||
dashboard_import:
|
password: !secret wifi_password
|
||||||
package_import_url: github://athom-tech/athom-configs/athom-rgbww-light.yaml
|
channel: 1
|
||||||
|
hidden: True
|
||||||
|
manual_ip:
|
||||||
|
static_ip: 10.42.100.12
|
||||||
|
gateway: 10.42.100.1
|
||||||
|
subnet: 255.255.255.0
|
||||||
|
|
||||||
binary_sensor:
|
binary_sensor:
|
||||||
- platform: status
|
- platform: status
|
||||||
@@ -104,21 +101,6 @@ sensor:
|
|||||||
entity_category: "diagnostic"
|
entity_category: "diagnostic"
|
||||||
device_class: ""
|
device_class: ""
|
||||||
|
|
||||||
button:
|
|
||||||
- platform: restart
|
|
||||||
name: "Restart"
|
|
||||||
entity_category: config
|
|
||||||
|
|
||||||
- platform: factory_reset
|
|
||||||
name: "Factory Reset"
|
|
||||||
id: Reset
|
|
||||||
entity_category: config
|
|
||||||
|
|
||||||
- platform: safe_mode
|
|
||||||
name: "Safe Mode"
|
|
||||||
internal: false
|
|
||||||
entity_category: config
|
|
||||||
|
|
||||||
output:
|
output:
|
||||||
- platform: esp8266_pwm
|
- platform: esp8266_pwm
|
||||||
id: red_output
|
id: red_output
|
||||||
|
|||||||
@@ -72,21 +72,18 @@ api:
|
|||||||
ota:
|
ota:
|
||||||
- platform: esphome
|
- platform: esphome
|
||||||
|
|
||||||
logger:
|
|
||||||
|
|
||||||
mdns:
|
|
||||||
disabled: false
|
|
||||||
|
|
||||||
wifi:
|
wifi:
|
||||||
ssid: !secret wifi_ssid
|
|
||||||
password: !secret wifi_password
|
|
||||||
fast_connect: True
|
|
||||||
domain: .cloonar.smart
|
domain: .cloonar.smart
|
||||||
|
fast_connect: False
|
||||||
captive_portal:
|
networks:
|
||||||
|
- ssid: !secret wifi_ssid
|
||||||
dashboard_import:
|
password: !secret wifi_password
|
||||||
package_import_url: github://athom-tech/athom-configs/athom-rgbww-light.yaml
|
hidden: True
|
||||||
|
channel: 1
|
||||||
|
manual_ip:
|
||||||
|
static_ip: 10.42.100.13
|
||||||
|
gateway: 10.42.100.1
|
||||||
|
subnet: 255.255.255.0
|
||||||
|
|
||||||
binary_sensor:
|
binary_sensor:
|
||||||
- platform: status
|
- platform: status
|
||||||
@@ -115,21 +112,6 @@ sensor:
|
|||||||
entity_category: "diagnostic"
|
entity_category: "diagnostic"
|
||||||
device_class: ""
|
device_class: ""
|
||||||
|
|
||||||
button:
|
|
||||||
- platform: restart
|
|
||||||
name: "Restart"
|
|
||||||
entity_category: config
|
|
||||||
|
|
||||||
- platform: factory_reset
|
|
||||||
name: "Factory Reset"
|
|
||||||
id: Reset
|
|
||||||
entity_category: config
|
|
||||||
|
|
||||||
- platform: safe_mode
|
|
||||||
name: "Safe Mode"
|
|
||||||
internal: false
|
|
||||||
entity_category: config
|
|
||||||
|
|
||||||
output:
|
output:
|
||||||
- platform: esp8266_pwm
|
- platform: esp8266_pwm
|
||||||
id: red_output
|
id: red_output
|
||||||
|
|||||||
@@ -72,21 +72,17 @@ api:
|
|||||||
ota:
|
ota:
|
||||||
- platform: esphome
|
- platform: esphome
|
||||||
|
|
||||||
logger:
|
|
||||||
|
|
||||||
mdns:
|
|
||||||
disabled: false
|
|
||||||
|
|
||||||
wifi:
|
wifi:
|
||||||
ssid: !secret wifi_ssid
|
|
||||||
password: !secret wifi_password
|
|
||||||
fast_connect: True
|
|
||||||
domain: .cloonar.smart
|
domain: .cloonar.smart
|
||||||
|
fast_connect: False
|
||||||
captive_portal:
|
networks:
|
||||||
|
- ssid: !secret wifi_ssid
|
||||||
dashboard_import:
|
password: !secret wifi_password
|
||||||
package_import_url: github://athom-tech/athom-configs/athom-rgbww-light.yaml
|
hidden: True
|
||||||
|
manual_ip:
|
||||||
|
static_ip: 10.42.100.14
|
||||||
|
gateway: 10.42.100.1
|
||||||
|
subnet: 255.255.255.0
|
||||||
|
|
||||||
binary_sensor:
|
binary_sensor:
|
||||||
- platform: status
|
- platform: status
|
||||||
@@ -115,21 +111,6 @@ sensor:
|
|||||||
entity_category: "diagnostic"
|
entity_category: "diagnostic"
|
||||||
device_class: ""
|
device_class: ""
|
||||||
|
|
||||||
button:
|
|
||||||
- platform: restart
|
|
||||||
name: "Restart"
|
|
||||||
entity_category: config
|
|
||||||
|
|
||||||
- platform: factory_reset
|
|
||||||
name: "Factory Reset"
|
|
||||||
id: Reset
|
|
||||||
entity_category: config
|
|
||||||
|
|
||||||
- platform: safe_mode
|
|
||||||
name: "Safe Mode"
|
|
||||||
internal: false
|
|
||||||
entity_category: config
|
|
||||||
|
|
||||||
output:
|
output:
|
||||||
- platform: esp8266_pwm
|
- platform: esp8266_pwm
|
||||||
id: red_output
|
id: red_output
|
||||||
|
|||||||
@@ -72,21 +72,17 @@ api:
|
|||||||
ota:
|
ota:
|
||||||
- platform: esphome
|
- platform: esphome
|
||||||
|
|
||||||
logger:
|
|
||||||
|
|
||||||
mdns:
|
|
||||||
disabled: false
|
|
||||||
|
|
||||||
wifi:
|
wifi:
|
||||||
ssid: !secret wifi_ssid
|
|
||||||
password: !secret wifi_password
|
|
||||||
fast_connect: True
|
|
||||||
domain: .cloonar.smart
|
domain: .cloonar.smart
|
||||||
|
fast_connect: False
|
||||||
captive_portal:
|
networks:
|
||||||
|
- ssid: !secret wifi_ssid
|
||||||
dashboard_import:
|
password: !secret wifi_password
|
||||||
package_import_url: github://athom-tech/athom-configs/athom-rgbww-light.yaml
|
hidden: True
|
||||||
|
manual_ip:
|
||||||
|
static_ip: 10.42.100.15
|
||||||
|
gateway: 10.42.100.1
|
||||||
|
subnet: 255.255.255.0
|
||||||
|
|
||||||
binary_sensor:
|
binary_sensor:
|
||||||
- platform: status
|
- platform: status
|
||||||
@@ -115,21 +111,6 @@ sensor:
|
|||||||
entity_category: "diagnostic"
|
entity_category: "diagnostic"
|
||||||
device_class: ""
|
device_class: ""
|
||||||
|
|
||||||
button:
|
|
||||||
- platform: restart
|
|
||||||
name: "Restart"
|
|
||||||
entity_category: config
|
|
||||||
|
|
||||||
- platform: factory_reset
|
|
||||||
name: "Factory Reset"
|
|
||||||
id: Reset
|
|
||||||
entity_category: config
|
|
||||||
|
|
||||||
- platform: safe_mode
|
|
||||||
name: "Safe Mode"
|
|
||||||
internal: false
|
|
||||||
entity_category: config
|
|
||||||
|
|
||||||
output:
|
output:
|
||||||
- platform: esp8266_pwm
|
- platform: esp8266_pwm
|
||||||
id: red_output
|
id: red_output
|
||||||
|
|||||||
@@ -72,21 +72,18 @@ api:
|
|||||||
ota:
|
ota:
|
||||||
- platform: esphome
|
- platform: esphome
|
||||||
|
|
||||||
logger:
|
|
||||||
|
|
||||||
mdns:
|
|
||||||
disabled: false
|
|
||||||
|
|
||||||
wifi:
|
wifi:
|
||||||
ssid: !secret wifi_ssid
|
|
||||||
password: !secret wifi_password
|
|
||||||
fast_connect: True
|
|
||||||
domain: .cloonar.smart
|
domain: .cloonar.smart
|
||||||
|
fast_connect: False
|
||||||
captive_portal:
|
networks:
|
||||||
|
- ssid: !secret wifi_ssid
|
||||||
dashboard_import:
|
password: !secret wifi_password
|
||||||
package_import_url: github://athom-tech/athom-configs/athom-rgbww-light.yaml
|
hidden: True
|
||||||
|
channel: 1
|
||||||
|
manual_ip:
|
||||||
|
static_ip: 10.42.100.16
|
||||||
|
gateway: 10.42.100.1
|
||||||
|
subnet: 255.255.255.0
|
||||||
|
|
||||||
binary_sensor:
|
binary_sensor:
|
||||||
- platform: status
|
- platform: status
|
||||||
@@ -115,21 +112,6 @@ sensor:
|
|||||||
entity_category: "diagnostic"
|
entity_category: "diagnostic"
|
||||||
device_class: ""
|
device_class: ""
|
||||||
|
|
||||||
button:
|
|
||||||
- platform: restart
|
|
||||||
name: "Restart"
|
|
||||||
entity_category: config
|
|
||||||
|
|
||||||
- platform: factory_reset
|
|
||||||
name: "Factory Reset"
|
|
||||||
id: Reset
|
|
||||||
entity_category: config
|
|
||||||
|
|
||||||
- platform: safe_mode
|
|
||||||
name: "Safe Mode"
|
|
||||||
internal: false
|
|
||||||
entity_category: config
|
|
||||||
|
|
||||||
output:
|
output:
|
||||||
- platform: esp8266_pwm
|
- platform: esp8266_pwm
|
||||||
id: red_output
|
id: red_output
|
||||||
|
|||||||
@@ -16,8 +16,10 @@
|
|||||||
./modules/networking.nix
|
./modules/networking.nix
|
||||||
./modules/setupnetwork.nix
|
./modules/setupnetwork.nix
|
||||||
./modules/firewall.nix
|
./modules/firewall.nix
|
||||||
./modules/dhcp4.nix
|
# ./modules/dhcp4.nix
|
||||||
./modules/unbound.nix
|
# ./modules/unbound.nix
|
||||||
|
|
||||||
|
./modules/dnsmasq.nix
|
||||||
./modules/avahi.nix
|
./modules/avahi.nix
|
||||||
./modules/openconnect.nix
|
./modules/openconnect.nix
|
||||||
./modules/wireguard.nix
|
./modules/wireguard.nix
|
||||||
@@ -33,7 +35,7 @@
|
|||||||
# ./modules/vscode-server.nix # Add VS Code Server microvm
|
# ./modules/vscode-server.nix # Add VS Code Server microvm
|
||||||
|
|
||||||
./modules/ai-mailer.nix
|
./modules/ai-mailer.nix
|
||||||
./modules/wazuh.nix
|
# ./modules/wazuh.nix
|
||||||
|
|
||||||
# web
|
# web
|
||||||
./modules/web
|
./modules/web
|
||||||
@@ -52,7 +54,8 @@
|
|||||||
./modules/deconz.nix
|
./modules/deconz.nix
|
||||||
# ./modules/mopidy.nix
|
# ./modules/mopidy.nix
|
||||||
# ./modules/mosquitto.nix
|
# ./modules/mosquitto.nix
|
||||||
./modules/snapserver.nix
|
# ./modules/snapserver.nix
|
||||||
|
./modules/lms.nix
|
||||||
|
|
||||||
# gaming
|
# gaming
|
||||||
# ./modules/palworld.nix
|
# ./modules/palworld.nix
|
||||||
|
|||||||
160
hosts/fw/modules/dnsmasq.nix
Normal file
160
hosts/fw/modules/dnsmasq.nix
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
{ config, ... }: {
|
||||||
|
services.resolved.enable = false;
|
||||||
|
|
||||||
|
services.dnsmasq = {
|
||||||
|
enable = true;
|
||||||
|
settings = {
|
||||||
|
port = "53";
|
||||||
|
bind-interfaces = true; # force dnsmasq to bind immediately
|
||||||
|
expand-hosts = true;
|
||||||
|
|
||||||
|
log-dhcp = true;
|
||||||
|
|
||||||
|
server = [
|
||||||
|
"/epicenter.works/10.50.60.1"
|
||||||
|
"/akvorrat.at/10.50.60.1"
|
||||||
|
"9.9.9.9"
|
||||||
|
"149.112.112.11"
|
||||||
|
];
|
||||||
|
|
||||||
|
interface = [
|
||||||
|
"lan"
|
||||||
|
"server"
|
||||||
|
"infrastructure"
|
||||||
|
"multimedia"
|
||||||
|
"guest"
|
||||||
|
"smart"
|
||||||
|
];
|
||||||
|
|
||||||
|
domain = [
|
||||||
|
"cloonar.com,lan"
|
||||||
|
"cloonar.com,server"
|
||||||
|
"cloonar.com,infrastructure"
|
||||||
|
"cloonar.multimedia,multimedia"
|
||||||
|
"cloonar.smart,smart"
|
||||||
|
"cloonar.guest,guest"
|
||||||
|
];
|
||||||
|
|
||||||
|
dhcp-option = [
|
||||||
|
"lan,15,cloonar.com" # domain name
|
||||||
|
"lan,3,${config.networkPrefix}.96.1" # Gateway
|
||||||
|
"lan,6,${config.networkPrefix}.96.1" # DNS
|
||||||
|
"server,15,cloonar.com"
|
||||||
|
"server,3,${config.networkPrefix}.97.1"
|
||||||
|
"server,6,${config.networkPrefix}.97.1"
|
||||||
|
"infrastructure,15,cloonar.com"
|
||||||
|
"infrastructure,3,${config.networkPrefix}.101.1"
|
||||||
|
"infrastructure,6,${config.networkPrefix}.101.1"
|
||||||
|
"multimedia,15,cloonar.multimedia"
|
||||||
|
"multimedia,3,${config.networkPrefix}.99.1"
|
||||||
|
"multimedia,6,${config.networkPrefix}.99.1"
|
||||||
|
"smart,15,cloonar.smart"
|
||||||
|
"smart,3,${config.networkPrefix}.100.1"
|
||||||
|
"smart,6,${config.networkPrefix}.100.1"
|
||||||
|
"guest,15,cloonar.guest"
|
||||||
|
"guest,3,${config.networkPrefix}.254.1"
|
||||||
|
"guest,6,9.9.9.9"
|
||||||
|
];
|
||||||
|
|
||||||
|
dhcp-range = [
|
||||||
|
"lan,${config.networkPrefix}.96.100,${config.networkPrefix}.96.200,24h"
|
||||||
|
"server,${config.networkPrefix}.97.100,${config.networkPrefix}.97.200,24h"
|
||||||
|
"infrastructure,${config.networkPrefix}.101.100,${config.networkPrefix}.101.200,24h"
|
||||||
|
"multimedia,${config.networkPrefix}.99.100,${config.networkPrefix}.99.200,24h"
|
||||||
|
"smart,${config.networkPrefix}.100.100,${config.networkPrefix}.100.200,24h"
|
||||||
|
"guest,${config.networkPrefix}.254.100,${config.networkPrefix}.254.200,24h"
|
||||||
|
];
|
||||||
|
|
||||||
|
dhcp-host = [
|
||||||
|
"30:05:5c:56:62:37,${config.networkPrefix}.96.100,brn30055c566237"
|
||||||
|
"24:df:a7:b1:1b:74,${config.networkPrefix}.96.101,rmproplus-b1-1b-74"
|
||||||
|
|
||||||
|
"1a:c4:04:6e:29:bd,${config.networkPrefix}.97.2,omada"
|
||||||
|
"02:00:00:00:00:03,${config.networkPrefix}.97.5,web-02"
|
||||||
|
"02:00:00:00:00:04,${config.networkPrefix}.97.6,matrix"
|
||||||
|
"ea:db:d4:c1:18:ba,${config.networkPrefix}.97.50,git"
|
||||||
|
"c2:4f:64:dd:13:0c,${config.networkPrefix}.97.20,home-assistant"
|
||||||
|
"1a:c4:04:6e:29:02,${config.networkPrefix}.101.25,deconz"
|
||||||
|
|
||||||
|
"c4:a7:2b:c7:ea:30,${config.networkPrefix}.99.10,metz"
|
||||||
|
"f0:2f:9e:d4:3b:21,${config.networkPrefix}.99.11,firetv-living"
|
||||||
|
"e4:2a:ac:32:3f:79,${config.networkPrefix}.99.13,xbox"
|
||||||
|
"f0:2f:9e:c1:74:72,${config.networkPrefix}.99.21,firetv-bedroom"
|
||||||
|
"30:05:5c:56:62:37,${config.networkPrefix}.99.100,brn30055c566237"
|
||||||
|
|
||||||
|
"fc:ee:28:03:63:e9,${config.networkPrefix}.100.148,k1c"
|
||||||
|
"cc:50:e3:bc:27:64,${config.networkPrefix}.100.112,Nuki_Bridge_1A753F72"
|
||||||
|
"34:6f:24:f3:af:ad,${config.networkPrefix}.100.137,daikin86604"
|
||||||
|
"34:6f:24:c1:f8:54,${config.networkPrefix}.100.139,daikin53800"
|
||||||
|
];
|
||||||
|
|
||||||
|
address = [
|
||||||
|
"/fw.cloonar.com/${config.networkPrefix}.97.1"
|
||||||
|
"/omada.cloonar.com/${config.networkPrefix}.97.2"
|
||||||
|
"/pc.cloonar.com/${config.networkPrefix}.96.5"
|
||||||
|
"/home-assistant.cloonar.com/${config.networkPrefix}.97.20"
|
||||||
|
"/mopidy.cloonar.com/${config.networkPrefix}.97.21"
|
||||||
|
"/snapcast.cloonar.com/${config.networkPrefix}.97.21"
|
||||||
|
"/git.cloonar.com/${config.networkPrefix}.97.50"
|
||||||
|
"/feeds.cloonar.com/188.34.191.144"
|
||||||
|
|
||||||
|
"/stage.wsw.at/10.254.235.22"
|
||||||
|
"/prod.wsw.at/10.254.217.23"
|
||||||
|
"/piwik.wohnservice-wien.at/10.254.240.109"
|
||||||
|
"/wohnberatung-wien.at/10.254.240.109"
|
||||||
|
"/wohnpartner-wien.at/10.254.240.109"
|
||||||
|
"/wohnservice-wien.at/10.254.240.109"
|
||||||
|
"/mieterhilfe.at/10.254.240.109"
|
||||||
|
"/wienbautvor.at/10.254.240.109"
|
||||||
|
"/wienwohntbesser.at/10.254.240.109"
|
||||||
|
"/a.stage.wohnberatung-wien.at/10.254.240.110"
|
||||||
|
"/a.stage.wohnpartner-wien.at/10.254.240.110"
|
||||||
|
"/a.stage.wohnservice-wien.at/10.254.240.110"
|
||||||
|
"/a.stage.mieterhilfe.at/10.254.240.110"
|
||||||
|
"/a.stage.wienbautvor.at/10.254.240.110"
|
||||||
|
"/a.stage.wienwohntbesser.at/10.254.240.110"
|
||||||
|
"/b.stage.wohnberatung-wien.at/10.254.240.110"
|
||||||
|
"/b.stage.wohnpartner-wien.at/10.254.240.110"
|
||||||
|
"/b.stage.wohnservice-wien.at/10.254.240.110"
|
||||||
|
"/b.stage.mieterhilfe.at/10.254.240.110"
|
||||||
|
"/b.stage.wienbautvor.at/10.254.240.110"
|
||||||
|
"/b.stage.wienwohntbesser.at/10.254.240.110"
|
||||||
|
|
||||||
|
"/web.hilgenberg-gmbh.de/91.107.197.169"
|
||||||
|
# gaming
|
||||||
|
"/foundry-vtt.cloonar.com/${config.networkPrefix}.97.5"
|
||||||
|
|
||||||
|
"/deconz.cloonar.multimedia/${config.networkPrefix}.97.22"
|
||||||
|
|
||||||
|
"/ddl-warez.to/172.67.184.30"
|
||||||
|
"/cdnjs.cloudflare.com/104.17.24.14"
|
||||||
|
|
||||||
|
# esphome devices
|
||||||
|
"/livingroom-bulb-1.cloonar.smart/${config.networkPrefix}.100.11"
|
||||||
|
"/livingroom-bulb-2.cloonar.smart/${config.networkPrefix}.100.12"
|
||||||
|
"/livingroom-bulb-3.cloonar.smart/${config.networkPrefix}.100.13"
|
||||||
|
"/livingroom-bulb-4.cloonar.smart/${config.networkPrefix}.100.14"
|
||||||
|
"/livingroom-bulb-5.cloonar.smart/${config.networkPrefix}.100.15"
|
||||||
|
"/livingroom-bulb-6.cloonar.smart/${config.networkPrefix}.100.16"
|
||||||
|
|
||||||
|
"/bedroom-bulb-0.cloonar.smart/${config.networkPrefix}.100.21"
|
||||||
|
"/bedroom-bulb-0.cloonar.smart/${config.networkPrefix}.100.22"
|
||||||
|
"/bedroom-bulb-0.cloonar.smart/${config.networkPrefix}.100.23"
|
||||||
|
"/bedroom-bulb-0.cloonar.smart/${config.networkPrefix}.100.24"
|
||||||
|
|
||||||
|
"/hallway-bulb-0.cloonar.smart/${config.networkPrefix}.100.31"
|
||||||
|
"/hallway-bulb-0.cloonar.smart/${config.networkPrefix}.100.32"
|
||||||
|
|
||||||
|
"/bath-bulb-0.cloonar.smart/${config.networkPrefix}.100.41"
|
||||||
|
"/bath-bulb-0.cloonar.smart/${config.networkPrefix}.100.42"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.dnsmasq = {
|
||||||
|
requires = [ "network-online.target" ];
|
||||||
|
after = [ "network-online.target" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.firewall.allowedUDPPorts = [ 53 67 ];
|
||||||
|
}
|
||||||
@@ -8,6 +8,18 @@
|
|||||||
"cloonar-fw" = {
|
"cloonar-fw" = {
|
||||||
family = "inet";
|
family = "inet";
|
||||||
content = ''
|
content = ''
|
||||||
|
chain snap-qos-raw {
|
||||||
|
type filter hook prerouting priority raw; policy accept;
|
||||||
|
tcp dport 1704 counter mark set 10 comment "Mark Snapcast traffic"
|
||||||
|
tcp dport 3483 counter mark set 10 comment "Mark Squezelite traffic"
|
||||||
|
udp dport 3483 counter mark set 10 comment "Mark Squezelite traffic"
|
||||||
|
}
|
||||||
|
|
||||||
|
chain snap-qos-mangle {
|
||||||
|
type filter hook postrouting priority mangle + 10; policy accept;
|
||||||
|
mark 10 counter ip dscp set cs3 comment "Tag Snapcast with CS3"
|
||||||
|
}
|
||||||
|
|
||||||
chain output {
|
chain output {
|
||||||
type filter hook output priority 100; policy accept;
|
type filter hook output priority 100; policy accept;
|
||||||
}
|
}
|
||||||
@@ -22,6 +34,7 @@
|
|||||||
type filter hook input priority filter; policy drop;
|
type filter hook input priority filter; policy drop;
|
||||||
iifname "lo" accept comment "trusted interfaces"
|
iifname "lo" accept comment "trusted interfaces"
|
||||||
iifname "lan" counter accept comment "Spice"
|
iifname "lan" counter accept comment "Spice"
|
||||||
|
iifname { "server", "vserver", "vm-*", "lan", "wg_cloonar" } counter accept comment "allow trusted to router"
|
||||||
ct state vmap { invalid : drop, established : accept, related : accept, new : jump input-allow, untracked : jump input-allow }
|
ct state vmap { invalid : drop, established : accept, related : accept, new : jump input-allow, untracked : jump input-allow }
|
||||||
tcp flags syn / fin,syn,rst,ack log prefix "refused connection: " level info
|
tcp flags syn / fin,syn,rst,ack log prefix "refused connection: " level info
|
||||||
}
|
}
|
||||||
@@ -34,11 +47,14 @@
|
|||||||
iifname "lan" tcp dport 5931 counter accept comment "Spice"
|
iifname "lan" tcp dport 5931 counter accept comment "Spice"
|
||||||
iifname { "server", "vserver", "vm-*", "lan", "wg_cloonar" } counter accept comment "allow trusted to router"
|
iifname { "server", "vserver", "vm-*", "lan", "wg_cloonar" } counter accept comment "allow trusted to router"
|
||||||
iifname { "multimedia", "smart", "infrastructure", "podman0", "setup" } udp dport { 53, 5353 } counter accept comment "DNS"
|
iifname { "multimedia", "smart", "infrastructure", "podman0", "setup" } udp dport { 53, 5353 } counter accept comment "DNS"
|
||||||
|
iifname { "multimedia", "smart", "infrastructure", "server", "lan", "guest" } udp dport { 67 } counter accept comment "DHCP"
|
||||||
iifname { "wan", "multimedia" } icmp type { echo-request, destination-unreachable, time-exceeded } counter accept comment "Allow select ICMP"
|
iifname { "wan", "multimedia" } icmp type { echo-request, destination-unreachable, time-exceeded } counter accept comment "Allow select ICMP"
|
||||||
|
|
||||||
# Accept mDNS for avahi reflection
|
# Accept mDNS for avahi reflection
|
||||||
iifname "server" ip saddr ${config.networkPrefix}.97.20/32 tcp dport { llmnr } counter accept
|
iifname "server" ip saddr ${config.networkPrefix}.97.20/32 tcp dport { llmnr } counter accept
|
||||||
iifname "server" ip saddr ${config.networkPrefix}.97.20/32 udp dport { mdns, llmnr } counter accept
|
iifname "server" ip saddr ${config.networkPrefix}.97.20/32 udp dport { mdns, llmnr } counter accept
|
||||||
|
iifname "server" udp dport 5353 ip daddr 224.0.0.251 counter accept comment "Avahi mDNS"
|
||||||
|
iifname "lan" udp dport 5353 ip daddr 224.0.0.251 counter accept comment "Avahi mDNS"
|
||||||
|
|
||||||
# Allow all returning traffic
|
# Allow all returning traffic
|
||||||
ct state { established, related } counter accept
|
ct state { established, related } counter accept
|
||||||
@@ -79,10 +95,24 @@
|
|||||||
# multimedia airplay
|
# multimedia airplay
|
||||||
iifname "multimedia" oifname { "lan" } counter accept
|
iifname "multimedia" oifname { "lan" } counter accept
|
||||||
iifname "multimedia" oifname "server" tcp dport { 1704, 1705 } counter accept
|
iifname "multimedia" oifname "server" tcp dport { 1704, 1705 } counter accept
|
||||||
|
iifname "multimedia" oifname "server" tcp dport { 3483, 9000 } counter accept
|
||||||
|
iifname "multimedia" oifname "server" udp dport { 3483 } counter accept
|
||||||
|
iifname "multimedia" oifname "server" icmp type { echo-request, destination-unreachable, time-exceeded } counter accept comment "Allow select ICMP"
|
||||||
iifname "lan" oifname "server" udp dport { 5000, 5353, 6001 - 6011 } counter accept
|
iifname "lan" oifname "server" udp dport { 5000, 5353, 6001 - 6011 } counter accept
|
||||||
# avahi
|
# avahi
|
||||||
iifname "server" ip saddr ${config.networkPrefix}.97.20/32 oifname { "lan" } counter accept
|
iifname "server" ip saddr ${config.networkPrefix}.97.20/32 oifname { "lan" } counter accept
|
||||||
|
|
||||||
|
# Allow Chromecast
|
||||||
|
iifname "lan" oifname "server" udp dport 5353 ip daddr 224.0.0.251 counter accept comment "mDNS query LAN→Server"
|
||||||
|
iifname "server" oifname "lan" udp sport 5353 ip saddr 224.0.0.251 counter accept comment "mDNS response Server→LAN"
|
||||||
|
iifname "lan" oifname "server" tcp dport 9881 counter accept comment "chromecast"
|
||||||
|
|
||||||
|
# SSDP / UPnP discovery if needed
|
||||||
|
iifname { "lan", "server" } oifname { "server", "lan" } \
|
||||||
|
udp dport 1900 ip daddr 239.255.255.250 counter accept comment "SSDP query"
|
||||||
|
iifname { "lan", "server" } oifname { "server", "lan" } \
|
||||||
|
udp sport 1900 ip saddr 239.255.255.250 counter accept comment "SSDP response"
|
||||||
|
|
||||||
# smart home coap
|
# smart home coap
|
||||||
iifname "smart" oifname "server" ip daddr ${config.networkPrefix}.97.20/32 udp dport { 5683 } counter accept
|
iifname "smart" oifname "server" ip daddr ${config.networkPrefix}.97.20/32 udp dport { 5683 } counter accept
|
||||||
iifname "smart" oifname "server" ip daddr ${config.networkPrefix}.97.20/32 tcp dport { 1883 } counter accept
|
iifname "smart" oifname "server" ip daddr ${config.networkPrefix}.97.20/32 tcp dport { 1883 } counter accept
|
||||||
|
|||||||
@@ -421,21 +421,62 @@
|
|||||||
"light.bathroom_bulb_2"
|
"light.bathroom_bulb_2"
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
{
|
|
||||||
platform = "switch";
|
|
||||||
name = "Hallway Switch";
|
|
||||||
entity_id = "switch.hallway";
|
|
||||||
}
|
|
||||||
{
|
{
|
||||||
platform = "group";
|
platform = "group";
|
||||||
name = "Hallway Lights";
|
name = "Hallway Lights";
|
||||||
all = true;
|
all = true;
|
||||||
entities = [
|
entities = [
|
||||||
"light.hallway_switch"
|
"light.hallway_light_switch_mini_switch"
|
||||||
"light.hallway_bulb_1"
|
"light.hallway_bulb_1"
|
||||||
"light.hallway_bulb_2"
|
"light.hallway_bulb_2"
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
platform = "template";
|
||||||
|
lights = {
|
||||||
|
hallway_group_proxy = {
|
||||||
|
friendly_name = "Hallway Lights (Proxy)";
|
||||||
|
# follow the real group’s on/off state
|
||||||
|
value_template = "{{ is_state('light.hallway_lights','on') }}";
|
||||||
|
turn_on = {
|
||||||
|
service = "light.turn_on";
|
||||||
|
data = { entity_id = "light.hallway_lights"; };
|
||||||
|
};
|
||||||
|
turn_off = {
|
||||||
|
service = "light.turn_off";
|
||||||
|
data = { entity_id = "light.hallway_lights"; };
|
||||||
|
};
|
||||||
|
# brightness support
|
||||||
|
set_level = {
|
||||||
|
service = "light.turn_on";
|
||||||
|
data_template = {
|
||||||
|
entity_id = "light.hallway_lights";
|
||||||
|
brightness = "{{ brightness }}";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
# color temperature support (if you have CT-capable bulbs)
|
||||||
|
set_temperature = {
|
||||||
|
service = "light.turn_on";
|
||||||
|
data_template = {
|
||||||
|
entity_id = "light.hallway_lights";
|
||||||
|
color_temp = "{{ color_temp }}";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
# RGB color support
|
||||||
|
set_color = {
|
||||||
|
service = "light.turn_on";
|
||||||
|
data_template = {
|
||||||
|
entity_id = "light.hallway_lights";
|
||||||
|
rgb_color = [ "{{ red }}" "{{ green }}" "{{ blue }}" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
# always report as “available”
|
||||||
|
availability_template = "true";
|
||||||
|
# declare which color modes you need
|
||||||
|
supported_color_modes = [ "brightness" "color_temp" "rgb" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
{
|
{
|
||||||
platform = "switch";
|
platform = "switch";
|
||||||
name = "Toilet Switch";
|
name = "Toilet Switch";
|
||||||
|
|||||||
@@ -1,4 +1,9 @@
|
|||||||
{
|
let
|
||||||
|
devices = [
|
||||||
|
"device_tracker.dominiks_iphone"
|
||||||
|
"device_tracker.dominiks_mp01"
|
||||||
|
];
|
||||||
|
in {
|
||||||
services.home-assistant.extraComponents = [
|
services.home-assistant.extraComponents = [
|
||||||
"nuki"
|
"nuki"
|
||||||
];
|
];
|
||||||
@@ -9,9 +14,7 @@
|
|||||||
mode = "restart";
|
mode = "restart";
|
||||||
trigger = {
|
trigger = {
|
||||||
platform = "state";
|
platform = "state";
|
||||||
entity_id = [
|
entity_id = devices;
|
||||||
"device_tracker.dominiks_iphone"
|
|
||||||
];
|
|
||||||
from = "not_home";
|
from = "not_home";
|
||||||
to = "home";
|
to = "home";
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -494,6 +494,12 @@
|
|||||||
entity_id = "script.turn_on_tv";
|
entity_id = "script.turn_on_tv";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
service = "media_player.turn_off";
|
||||||
|
target = {
|
||||||
|
entity_id = "media_player.marantz_sr6015";
|
||||||
|
};
|
||||||
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
{
|
{
|
||||||
|
services.home-assistant.extraComponents = [ "squeezebox" ];
|
||||||
services.home-assistant.config = {
|
services.home-assistant.config = {
|
||||||
"automation toilet music" = {
|
"automation toilet music" = {
|
||||||
alias = "toilet music";
|
alias = "toilet music";
|
||||||
trigger = {
|
trigger = {
|
||||||
platform = "state";
|
platform = "state";
|
||||||
entity_id = "light.toilett_lights";
|
entity_id = "light.toilet_switch";
|
||||||
};
|
};
|
||||||
action = [
|
action = [
|
||||||
{
|
{
|
||||||
@@ -13,10 +14,52 @@
|
|||||||
entity_id = "media_player.music_toilet_snapcast_client";
|
entity_id = "media_player.music_toilet_snapcast_client";
|
||||||
};
|
};
|
||||||
data = {
|
data = {
|
||||||
is_volume_muted = "{{ trigger.to_state.state == 'off' }}";
|
is_volume_muted = "{{ trigger.to_state.state != 'on' }}";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
"automation bathroom music" = {
|
||||||
|
alias = "bathroom music";
|
||||||
|
trigger = {
|
||||||
|
platform = "state";
|
||||||
|
entity_id = "light.bathroom_switch";
|
||||||
|
};
|
||||||
|
action = [
|
||||||
|
{
|
||||||
|
service = "media_player.volume_mute";
|
||||||
|
target = {
|
||||||
|
entity_id = "media_player.music_bathroom_snapcast_client";
|
||||||
|
};
|
||||||
|
data = {
|
||||||
|
is_volume_muted = "{{ trigger.to_state.state != 'on' }}";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
"automation piano" = {
|
||||||
|
alias = "piano";
|
||||||
|
trigger = {
|
||||||
|
platform = "state";
|
||||||
|
entity_id = "media_player.music_piano_snapcast_client";
|
||||||
|
attribute = "is_volume_muted";
|
||||||
|
};
|
||||||
|
condition = [
|
||||||
|
{
|
||||||
|
condition = "template";
|
||||||
|
value_template = "{{ trigger.from_state.state != 'unavailable' }}";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
condition = "template";
|
||||||
|
value_template = "{{ state_attr('media_player.music_piano_snapcast_client', 'is_volume_muted') == true or state_attr('media_player.music_piano_snapcast_client', 'is_volume_muted') == false }}";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
action = {
|
||||||
|
service = "switch.turn_on";
|
||||||
|
target = {
|
||||||
|
entity_id = "switch.piano_switch_power";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,31 +1,5 @@
|
|||||||
{
|
{
|
||||||
services.home-assistant = {
|
services.home-assistant = {
|
||||||
extraComponents = [ "snapcast" ];
|
extraComponents = [ "snapcast" ];
|
||||||
config = {
|
|
||||||
"automation piano" = {
|
|
||||||
alias = "piano";
|
|
||||||
trigger = {
|
|
||||||
platform = "state";
|
|
||||||
entity_id = "media_player.music_piano_snapcast_client";
|
|
||||||
attribute = "is_volume_muted";
|
|
||||||
};
|
|
||||||
condition = [
|
|
||||||
{
|
|
||||||
condition = "template";
|
|
||||||
value_template = "{{ trigger.from_state.state != 'unavailable' }}";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
condition = "template";
|
|
||||||
value_template = "{{ state_attr('media_player.music_piano_snapcast_client', 'is_volume_muted') == true or state_attr('media_player.music_piano_snapcast_client', 'is_volume_muted') == false }}";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
action = {
|
|
||||||
service = "switch.turn_on";
|
|
||||||
target = {
|
|
||||||
entity_id = "switch.piano_switch_power";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
88
hosts/fw/modules/lms.nix
Normal file
88
hosts/fw/modules/lms.nix
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
{ pkgs, config, lib, python3Packages, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
lmsDomain = "lms.cloonar.com";
|
||||||
|
networkPrefix = config.networkPrefix;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
security.acme.certs."${lmsDomain}" = {
|
||||||
|
group = "nginx";
|
||||||
|
};
|
||||||
|
|
||||||
|
sops.secrets.lms-spotify = { };
|
||||||
|
|
||||||
|
containers.lms = {
|
||||||
|
autoStart = true;
|
||||||
|
ephemeral = false;
|
||||||
|
privateNetwork = true;
|
||||||
|
hostBridge = "server";
|
||||||
|
|
||||||
|
hostAddress = "${networkPrefix}.97.2";
|
||||||
|
localAddress = "${networkPrefix}.97.21/24";
|
||||||
|
|
||||||
|
extraFlags = [ "--capability=CAP_NET_ADMIN" ];
|
||||||
|
|
||||||
|
bindMounts = {
|
||||||
|
"/var/lib/acme/lms/" = {
|
||||||
|
hostPath = config.security.acme.certs.${lmsDomain}.directory;
|
||||||
|
isReadOnly = true;
|
||||||
|
};
|
||||||
|
"/run/secrets/lms-spotify" = {
|
||||||
|
hostPath = config.sops.secrets.lms-spotify.path;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = { pkgs, lib, config, ... }:
|
||||||
|
let
|
||||||
|
in
|
||||||
|
{
|
||||||
|
networking = {
|
||||||
|
hostName = "lms";
|
||||||
|
useHostResolvConf = false;
|
||||||
|
defaultGateway = {
|
||||||
|
address = "${networkPrefix}.97.1";
|
||||||
|
interface = "eth0";
|
||||||
|
};
|
||||||
|
nameservers = [ "${networkPrefix}.97.1" ];
|
||||||
|
firewall.enable = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
environment.systemPackages = with pkgs; [
|
||||||
|
slimserver # Logitech/Lyrion Media Server
|
||||||
|
];
|
||||||
|
|
||||||
|
services.slimserver = {
|
||||||
|
enable = true;
|
||||||
|
package = pkgs.slimserver;
|
||||||
|
};
|
||||||
|
|
||||||
|
# make LMS discoverable via mDNS/Avahi
|
||||||
|
services.avahi = {
|
||||||
|
enable = true;
|
||||||
|
publish.enable = true;
|
||||||
|
publish.userServices = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
services.nginx.enable = true;
|
||||||
|
services.nginx.virtualHosts."${lmsDomain}" = {
|
||||||
|
sslCertificate = "/var/lib/acme/lms/fullchain.pem";
|
||||||
|
sslCertificateKey = "/var/lib/acme/lms/key.pem";
|
||||||
|
sslTrustedCertificate = "/var/lib/acme/lms/chain.pem";
|
||||||
|
forceSSL = true;
|
||||||
|
extraConfig = "proxy_buffering off;";
|
||||||
|
|
||||||
|
locations."/".extraConfig = ''
|
||||||
|
proxy_pass http://127.0.0.1:9000/;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_redirect http:// https://;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection $connection_upgrade;
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
system.stateVersion = "23.05";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -261,6 +261,10 @@ in {
|
|||||||
enable = true;
|
enable = true;
|
||||||
path = with pkgs; [ unbound inotify-tools ];
|
path = with pkgs; [ unbound inotify-tools ];
|
||||||
script = ''
|
script = ''
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# readFile and readFileUnique as before…
|
||||||
function readFile() {
|
function readFile() {
|
||||||
if [[ "''\$2" == "A" ]] ; then
|
if [[ "''\$2" == "A" ]] ; then
|
||||||
cat "''\$1" | tail -n +2 | while IFS=, read -r address hwaddr client_id valid_lifetime expire subnet_id fqdn_fwd fqdn_rev hostname state user_context
|
cat "''\$1" | tail -n +2 | while IFS=, read -r address hwaddr client_id valid_lifetime expire subnet_id fqdn_fwd fqdn_rev hostname state user_context
|
||||||
@@ -315,17 +319,25 @@ in {
|
|||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
function syncFile() {
|
function syncLeases() {
|
||||||
# readFileUnique "''\$1" "''\$2"
|
# 1) nuke all of our old lease records from unbound
|
||||||
while true; do
|
unbound-control list_local_data \
|
||||||
readFileUnique "''\$1" "''\$2"
|
| grep -E 'cloonar\.(com|multimedia|smart)|ip4\.arpa|in-addr\.arpa' \
|
||||||
sleep 10
|
| while read -r name type data; do
|
||||||
done
|
unbound-control local_data_remove "$name" "$type" "$data" \
|
||||||
|
> /dev/null 2>&1
|
||||||
|
done
|
||||||
|
|
||||||
|
# 2) re-push every current lease
|
||||||
|
readFileUnique "/var/lib/kea/dhcp4.leases" A
|
||||||
|
# if you need IPv6:
|
||||||
|
# readFileUnique "/var/lib/kea/dhcp6.leases" AAAA
|
||||||
}
|
}
|
||||||
|
|
||||||
syncFile "/var/lib/kea/dhcp4.leases" A &
|
while true; do
|
||||||
# syncFile "/var/lib/kea/dhcp6.leases" AAAA &
|
syncLeases
|
||||||
wait
|
sleep 10
|
||||||
|
done
|
||||||
'';
|
'';
|
||||||
wants = [ "network-online.target" "unbound.service" ];
|
wants = [ "network-online.target" "unbound.service" ];
|
||||||
after = [ "network-online.target" "unbound.service" ];
|
after = [ "network-online.target" "unbound.service" ];
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ matrix-shared-secret: ENC[AES256_GCM,data:67imd3m6WBeGP/5Msmjy8B6sP983jMyWzRIzWg
|
|||||||
palworld: ENC[AES256_GCM,data:rdqChPt4gSJHS1D60+HJ+4m5mg35JbC+pOmevK21Y95QyAIeyBLVGhRYlOaUcqdZM2e4atyTTSf6z4nHsm539ddCbW7J2DCdF5PQkrAGDmmdTVq+jyJAT8gTrbXXCglT1wvFYY5dbf2NKA4ASJIA8bdVNuwRZU0CtFiishzLuc9m8ZcGCNwQ/+xkMZgkUAHYRlEJAZyMpXR6KkFftiR05JRAFczD4N7GXPPe+vyvgXg7QBGtf20Qd4SGBUw0zI/SNTRmifHUuc4Z6+Fe9JHgvTc3uFcTMVnty0fEuL+a29liaVdAFq8BnqJfc5CNV401ZSUeMbG41lCn1cegP/WChs9J6HXNrhWDgiXa6ln++NoKcfOHIfZVbYOCoOxFR6+YWeBU2+sHmdwI9j5XQf5Ly2hmg12j0Ds2Cn8k4PG5aQP+HT2bedqyxwSt6fi97A0Osnh4ig7+DzYAjSNLewbYLzVdK39VdvB9hqLto+yFS3gAaeYOHwPwtqa+COI85c55lHiyKHlSwPhBqYaaiDu00lQTUzq9R5vz6F/l+T3bUjuna5RryUu8yhnk5DyK834KycTOg4ETcZTqro6prfiEBxc+Utsc9JvEtZgwFv6fsVLOu7nHxuiYuvseZ4YA8LlYdwPJboMPO2XsuhwWtT1uz/rh2orH7/vsXvzA/kF8NFemWBEMVLYA8byC5ze8doiGDYp4T5AAf10nJB1ceQ==,iv:gs78fxhvo9KlTaR5nzs12/LdgPChSFPHD2k4VQp3ARo=,tag:lpWBOi9xh2cWkS+71KD/UQ==,type:str]
|
palworld: ENC[AES256_GCM,data:rdqChPt4gSJHS1D60+HJ+4m5mg35JbC+pOmevK21Y95QyAIeyBLVGhRYlOaUcqdZM2e4atyTTSf6z4nHsm539ddCbW7J2DCdF5PQkrAGDmmdTVq+jyJAT8gTrbXXCglT1wvFYY5dbf2NKA4ASJIA8bdVNuwRZU0CtFiishzLuc9m8ZcGCNwQ/+xkMZgkUAHYRlEJAZyMpXR6KkFftiR05JRAFczD4N7GXPPe+vyvgXg7QBGtf20Qd4SGBUw0zI/SNTRmifHUuc4Z6+Fe9JHgvTc3uFcTMVnty0fEuL+a29liaVdAFq8BnqJfc5CNV401ZSUeMbG41lCn1cegP/WChs9J6HXNrhWDgiXa6ln++NoKcfOHIfZVbYOCoOxFR6+YWeBU2+sHmdwI9j5XQf5Ly2hmg12j0Ds2Cn8k4PG5aQP+HT2bedqyxwSt6fi97A0Osnh4ig7+DzYAjSNLewbYLzVdK39VdvB9hqLto+yFS3gAaeYOHwPwtqa+COI85c55lHiyKHlSwPhBqYaaiDu00lQTUzq9R5vz6F/l+T3bUjuna5RryUu8yhnk5DyK834KycTOg4ETcZTqro6prfiEBxc+Utsc9JvEtZgwFv6fsVLOu7nHxuiYuvseZ4YA8LlYdwPJboMPO2XsuhwWtT1uz/rh2orH7/vsXvzA/kF8NFemWBEMVLYA8byC5ze8doiGDYp4T5AAf10nJB1ceQ==,iv:gs78fxhvo9KlTaR5nzs12/LdgPChSFPHD2k4VQp3ARo=,tag:lpWBOi9xh2cWkS+71KD/UQ==,type:str]
|
||||||
ark: ENC[AES256_GCM,data:YYGyzoVIKI9Ac1zGOr0BEpd3fgBsvp1hSwAvfO07/EQdg8ufMWUkNvqNHDKN62ZK5A1NnY3JTA1p4gyZ4ryQeAOsbwqU1GSk2YKHFyPeEnpLz/Ml82KMsv7XPGXuKRXZ4v3UcLu0R8k1Q0gQsMWo4FjCs3FF5mVtJG/YWxxbCYHoBLJ/di5p0DgjuFgJBQknYBpuLzr+yIoeqEyN7XcGYAJO53trEJuOOxLILULifkqISHjZ66i5F1fHW0iUdRbmeWV4aOAeOrsQqXYv,iv:gJwV5ip84zHqpU0l0uESfWWOtcgihMvEEdLaeI+twcU=,tag:sy8udVQsKxV/jOqwhJmWAg==,type:str]
|
ark: ENC[AES256_GCM,data:YYGyzoVIKI9Ac1zGOr0BEpd3fgBsvp1hSwAvfO07/EQdg8ufMWUkNvqNHDKN62ZK5A1NnY3JTA1p4gyZ4ryQeAOsbwqU1GSk2YKHFyPeEnpLz/Ml82KMsv7XPGXuKRXZ4v3UcLu0R8k1Q0gQsMWo4FjCs3FF5mVtJG/YWxxbCYHoBLJ/di5p0DgjuFgJBQknYBpuLzr+yIoeqEyN7XcGYAJO53trEJuOOxLILULifkqISHjZ66i5F1fHW0iUdRbmeWV4aOAeOrsQqXYv,iv:gJwV5ip84zHqpU0l0uESfWWOtcgihMvEEdLaeI+twcU=,tag:sy8udVQsKxV/jOqwhJmWAg==,type:str]
|
||||||
firefox-sync: ENC[AES256_GCM,data:uAJAdyKAuXRuqCFl8742vIejU5RnAPpUxUFCC0s0QeXZR5oH2YOrDh+3vKUmckW4V1cIhSHoe+4+I4HuU5E73DDrJThfIzBEw+spo4HXwZf5KBtu3ujgX6/fSTlPWV7pEsDDsZ0y6ziKPADBDym8yEk0bU9nRedvTBUhVryo3aolzF/c+gJvdeDvKUYa8+8=,iv:yuvE4KG7z7Rp9ZNlLiJ2rh0keed3DuvrELzsfJu4+bs=,tag:HFo1A53Eva31NJ8fRE7TlA==,type:str]
|
firefox-sync: ENC[AES256_GCM,data:uAJAdyKAuXRuqCFl8742vIejU5RnAPpUxUFCC0s0QeXZR5oH2YOrDh+3vKUmckW4V1cIhSHoe+4+I4HuU5E73DDrJThfIzBEw+spo4HXwZf5KBtu3ujgX6/fSTlPWV7pEsDDsZ0y6ziKPADBDym8yEk0bU9nRedvTBUhVryo3aolzF/c+gJvdeDvKUYa8+8=,iv:yuvE4KG7z7Rp9ZNlLiJ2rh0keed3DuvrELzsfJu4+bs=,tag:HFo1A53Eva31NJ8fRE7TlA==,type:str]
|
||||||
|
knot-tsig-key: ENC[AES256_GCM,data:H2jEkRSVSIJl1dSolAXj9uUmzD6eEh9zPpoajZLxfuuFt7/LJF8aCEHyk+Q=,iv:9aqywuaILYtejuZGd+Cy8oErrHIoL2XhL1g9HtcUn/o=,tag:K3SnVEXGC/NhlchU7OyA6Q==,type:str]
|
||||||
sops:
|
sops:
|
||||||
kms: []
|
kms: []
|
||||||
gcp_kms: []
|
gcp_kms: []
|
||||||
@@ -59,8 +60,8 @@ sops:
|
|||||||
WXJpUUxadERyYUExRFMzNzBXaUVET3cKG9ZwWy5YvTr/BAw/i+ZJos5trwRvaW5j
|
WXJpUUxadERyYUExRFMzNzBXaUVET3cKG9ZwWy5YvTr/BAw/i+ZJos5trwRvaW5j
|
||||||
eV/SHiEteZZtCuCVFAp3iolE/mJyu97nA2yFwWaLN86h+/xkOJsdqA==
|
eV/SHiEteZZtCuCVFAp3iolE/mJyu97nA2yFwWaLN86h+/xkOJsdqA==
|
||||||
-----END AGE ENCRYPTED FILE-----
|
-----END AGE ENCRYPTED FILE-----
|
||||||
lastmodified: "2025-03-01T22:14:10Z"
|
lastmodified: "2025-05-01T20:36:09Z"
|
||||||
mac: ENC[AES256_GCM,data:UWwjvi8jLNgu4l7ldMYtkAATm3y5+BSxbCuPN/e1OC4/3ULYJndqFLfTOMpqQbj2+uHo3onelK4f0MAJuSH0oUx58CclkNBBLE0RXafxbowa7kJtTNDfTboJNqH7rFmhGhqCtHAOOpKBuowqoOUHP5BtzZfucra0Q/pIJt5lma0=,iv:iJEW/mTbizioPSN8G+WqHSipx8P6VCDrVG/Cmk+MBUc=,tag:L4OkeKec5AZdCrpUrnqcOA==,type:str]
|
mac: ENC[AES256_GCM,data:ZtXJcuwDpDlBl2xdRtMF1PwwqbW00Eps2ZZG5x4C2djAq+meXJCxKS9sNazQhMYFOqphQXe3JEhChykLxnJyWivY/Er1ig2sU6Ke1uVcfSP85B1/rpzhe/7QI+GBDWrkCk1O0xGKKj8fWt+Yv2MV8gw2XctdtJ9Md4imUhcK7zo=,iv:5NFH+7Z0alBiq/b94T40XJSCar2+BGaFB20z0Kc59fU=,tag:18n0tt17RNMyyE0eECH2kQ==,type:str]
|
||||||
pgp: []
|
pgp: []
|
||||||
unencrypted_suffix: _unencrypted
|
unencrypted_suffix: _unencrypted
|
||||||
version: 3.9.4
|
version: 3.9.4
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ in {
|
|||||||
./utils/modules/nur.nix
|
./utils/modules/nur.nix
|
||||||
./modules/appimage.nix
|
./modules/appimage.nix
|
||||||
./modules/sway/sway.nix
|
./modules/sway/sway.nix
|
||||||
./modules/printer.nix
|
# ./modules/printer.nix
|
||||||
# ./modules/cyberghost.nix
|
# ./modules/cyberghost.nix
|
||||||
./utils/modules/autoupgrade.nix
|
./utils/modules/autoupgrade.nix
|
||||||
./modules/puppeteer.nix
|
./modules/puppeteer.nix
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ let
|
|||||||
"media.ffmpeg.vaapi.enabled" = true;
|
"media.ffmpeg.vaapi.enabled" = true;
|
||||||
"media.ffmpeg.vaapi-drm-display.enabled" = true;
|
"media.ffmpeg.vaapi-drm-display.enabled" = true;
|
||||||
"gfx.webrender.all" = true;
|
"gfx.webrender.all" = true;
|
||||||
|
"xpinstall.signatures.required" = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
firefoxUserChrome = ''
|
firefoxUserChrome = ''
|
||||||
@@ -531,7 +532,7 @@ in
|
|||||||
|
|
||||||
programs.firefox = {
|
programs.firefox = {
|
||||||
enable = true;
|
enable = true;
|
||||||
package = pkgs.firefox.overrideAttrs (a: {
|
package = pkgs.firefox-devedition.overrideAttrs (a: {
|
||||||
postInstall = a.postInstall or "" + ''
|
postInstall = a.postInstall or "" + ''
|
||||||
wrapProgram "$out/bin/firefox" \
|
wrapProgram "$out/bin/firefox" \
|
||||||
export MOZ_ENABLE_WAYLAND=1
|
export MOZ_ENABLE_WAYLAND=1
|
||||||
@@ -558,6 +559,11 @@ in
|
|||||||
icon = "fingerprint";
|
icon = "fingerprint";
|
||||||
id = 1;
|
id = 1;
|
||||||
};
|
};
|
||||||
|
"dating" = {
|
||||||
|
color = "pink";
|
||||||
|
icon = "circle";
|
||||||
|
id = 5;
|
||||||
|
};
|
||||||
"cloonar technologies" = {
|
"cloonar technologies" = {
|
||||||
color = "red";
|
color = "red";
|
||||||
icon = "briefcase";
|
icon = "briefcase";
|
||||||
|
|||||||
@@ -8,7 +8,10 @@
|
|||||||
server_name = "code.cloonar.com";
|
server_name = "code.cloonar.com";
|
||||||
aliasgroup1 = "https://nextcloud.cloonar.com:443";
|
aliasgroup1 = "https://nextcloud.cloonar.com:443";
|
||||||
aliasgroup2 = "https://cloud.cloonar.com:443";
|
aliasgroup2 = "https://cloud.cloonar.com:443";
|
||||||
dictionaries = "en_US";
|
# Hannes
|
||||||
|
aliasgroup3 = "https://nx67898.your-storageshare.de:443";
|
||||||
|
aliasgroup4 = "https://hs-cloud.cloonar.com:443";
|
||||||
|
dictionaries = "en_GB en_US de_DE";
|
||||||
extra_params = "--o:ssl.enable=false --o:ssl.termination=true";
|
extra_params = "--o:ssl.enable=false --o:ssl.termination=true";
|
||||||
};
|
};
|
||||||
extraOptions = [
|
extraOptions = [
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ in
|
|||||||
enable = true;
|
enable = true;
|
||||||
hostName = "nextcloud.cloonar.com";
|
hostName = "nextcloud.cloonar.com";
|
||||||
https = true;
|
https = true;
|
||||||
package = nextcloud30;
|
package = pkgs.nextcloud31;
|
||||||
# Instead of using pkgs.nextcloud27Packages.apps,
|
# Instead of using pkgs.nextcloud27Packages.apps,
|
||||||
# we'll reference the package version specified above
|
# we'll reference the package version specified above
|
||||||
extraApps = {
|
extraApps = {
|
||||||
|
|||||||
7
hosts/web-arm/modules/postfix.nix
Normal file
7
hosts/web-arm/modules/postfix.nix
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{ pkgs, ... }: {
|
||||||
|
services.postfix = {
|
||||||
|
enable = true;
|
||||||
|
domain = "cloonar.com";
|
||||||
|
hostname = "web-arm.cloonar.com";
|
||||||
|
};
|
||||||
|
}
|
||||||
122
raspberry/picoreplayer.sh
Executable file
122
raspberry/picoreplayer.sh
Executable file
@@ -0,0 +1,122 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Must be run as root
|
||||||
|
if [[ $EUID -ne 0 ]]; then
|
||||||
|
echo "This script must be run as root. Try sudo $0 ..." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Default env file
|
||||||
|
ENV_FILE="./.env"
|
||||||
|
|
||||||
|
# PiCorePlayer version to use
|
||||||
|
PCP_VERSION="10.0.0"
|
||||||
|
BASE_URL="https://repo.pcplayer.org/insitu/piCorePlayer${PCP_VERSION}"
|
||||||
|
IMG_ZIP="piCorePlayer${PCP_VERSION}.img.xz"
|
||||||
|
DOWNLOAD_URL="${BASE_URL}/${IMG_ZIP}"
|
||||||
|
|
||||||
|
# Print usage
|
||||||
|
usage() {
|
||||||
|
cat <<EOF
|
||||||
|
Usage: sudo $0 --device <rpi-4|rpi-zero|rpi-zero-2> \
|
||||||
|
--sdcard </dev/sdX> \
|
||||||
|
[--env-file /path/to/.env]
|
||||||
|
|
||||||
|
--device Target board (rpi-4, rpi-zero, rpi-zero-2)
|
||||||
|
--sdcard Device node of the SD card (e.g. /dev/sdb)
|
||||||
|
--env-file File containing WIFI_SSID and WIFI_PSK (defaults to ./.env)
|
||||||
|
EOF
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Parse args
|
||||||
|
DEVICE="" SDCARD=""
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--device) DEVICE="$2"; shift 2;;
|
||||||
|
--sdcard) SDCARD="$2"; shift 2;;
|
||||||
|
--env-file) ENV_FILE="$2"; shift 2;;
|
||||||
|
-h|--help) usage;;
|
||||||
|
*) echo "Unknown option: $1" >&2; usage;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# Validate
|
||||||
|
if [[ -z "$DEVICE" || -z "$SDCARD" ]]; then
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
if [[ ! -b "$SDCARD" ]]; then
|
||||||
|
echo "Error: $SDCARD is not a block device." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [[ ! -f "$ENV_FILE" ]]; then
|
||||||
|
echo "Error: env file '$ENV_FILE' not found." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Load Wi-Fi credentials
|
||||||
|
source "$ENV_FILE"
|
||||||
|
if [[ -z "${WIFI_SSID:-}" || -z "${WIFI_PSK:-}" ]]; then
|
||||||
|
echo "Error: WIFI_SSID and WIFI_PSK must be set in $ENV_FILE" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Download if needed
|
||||||
|
if [[ ! -f "$IMG_ZIP" ]]; then
|
||||||
|
echo "Downloading $IMG_ZIP ..."
|
||||||
|
wget -q --show-progress "$DOWNLOAD_URL"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Flash image
|
||||||
|
echo "Flashing $IMG_ZIP to $SDCARD (will overwrite everything!)"
|
||||||
|
sync
|
||||||
|
xzcat "$IMG_ZIP" | dd of="$SDCARD" bs=4M status=progress
|
||||||
|
sync
|
||||||
|
|
||||||
|
# Determine partition suffixes (/dev/sdX1 vs /dev/mmcblk0p1)
|
||||||
|
if [[ "$SDCARD" =~ [0-9]$ ]]; then
|
||||||
|
PART1="${SDCARD}p1"; PART2="${SDCARD}p2"
|
||||||
|
else
|
||||||
|
PART1="${SDCARD}1"; PART2="${SDCARD}2"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Mount partitions
|
||||||
|
BOOT_MNT=$(mktemp -d)
|
||||||
|
ROOT_MNT=$(mktemp -d)
|
||||||
|
mount "$PART1" "$BOOT_MNT"
|
||||||
|
mount "$PART2" "$ROOT_MNT"
|
||||||
|
|
||||||
|
# Create hidden Wi-Fi config on boot partition
|
||||||
|
cat > "$BOOT_MNT/wpa_supplicant.conf" <<EOF
|
||||||
|
ctrl_interface=/var/run/wpa_supplicant
|
||||||
|
ctrl_interface_group=staff
|
||||||
|
country=AT
|
||||||
|
update_config=1
|
||||||
|
|
||||||
|
network={
|
||||||
|
ssid="$WIFI_SSID"
|
||||||
|
psk="$WIFI_PSK"
|
||||||
|
scan_ssid=1
|
||||||
|
key_mgmt=WPA-PSK
|
||||||
|
auth_alg=OPEN
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# If a Zero device, enable Hifiberry DAC+ and disable onboard audio
|
||||||
|
if [[ "$DEVICE" == "rpi-zero" || "$DEVICE" == "rpi-zero-2" ]]; then
|
||||||
|
cat >> "$BOOT_MNT/config.txt" <<EOF
|
||||||
|
|
||||||
|
# Hifiberry DAC+ overlay for Zero models
|
||||||
|
dtoverlay=hifiberry-dacplus-std
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
umount "$BOOT_MNT" "$ROOT_MNT"
|
||||||
|
rmdir "$BOOT_MNT" "$ROOT_MNT"
|
||||||
|
|
||||||
|
echo "Done! SD card is ready with PiCorePlayer ${PCP_VERSION} on $DEVICE,"
|
||||||
|
echo "hidden Wi-Fi '$WIFI_SSID'."
|
||||||
|
echo "Insert the SD card into the Pi and power it on."
|
||||||
|
echo "You can now connect to the PiCorePlayer web interface at http://pcp.local"
|
||||||
@@ -6,8 +6,8 @@ stdenv.mkDerivation rec {
|
|||||||
|
|
||||||
src = fetchgit {
|
src = fetchgit {
|
||||||
url = "https://github.com/dpolakovics/bento.git";
|
url = "https://github.com/dpolakovics/bento.git";
|
||||||
rev = "8d911a02dc9af222ffb5892bbddd4a3895893959";
|
rev = "73092673b194fd734d782f5b7e83dfbb5d169372";
|
||||||
sha256 = "sha256-9R3glZcjc+t8LKvo5HOAo+HzXFQ6GOtzehJpb7GjmYM=";
|
sha256 = "sha256-/37RJTjo+FJa1Flt59LrQbaJIcBid/z+Hy1xfhYGXNA=";
|
||||||
};
|
};
|
||||||
|
|
||||||
buildInputs = [ ];
|
buildInputs = [ ];
|
||||||
|
|||||||
Reference in New Issue
Block a user