Compare commits
302 Commits
3eb9ce0e89
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| d728722274 | |||
| 10fb8e88ce | |||
| 5f300d9e7b | |||
| 99ac2ea3b0 | |||
| 2caa36c0ab | |||
| 55c15c790d | |||
| 450d9d6457 | |||
| e08bf42eaa | |||
| 8e0e5c0d16 | |||
| ada9db7942 | |||
| 5995612407 | |||
| 5762916970 | |||
| dd456eab69 | |||
| 18a8fde66e | |||
| f97c9185c1 | |||
| 8bf4b185a1 | |||
| 8424d771f6 | |||
| 840f99a7e9 | |||
| 1b27bafd41 | |||
| 4770d671c0 | |||
| 28a7bed3b9 | |||
| 170becceb0 | |||
| 6e8f530537 | |||
| 209bafd70f | |||
| 1d182437db | |||
| 6c046a549e | |||
| 0a30a2ac23 | |||
| 82c15e8d26 | |||
| f277d089bd | |||
| 7ed345b8e8 | |||
| bd6b15b617 | |||
| 3282b7d634 | |||
| 21ed381d18 | |||
| 4500f41983 | |||
| 1d30eeb939 | |||
| 537f144885 | |||
| dbada3c509 | |||
| c8be707420 | |||
| fdba2c75c7 | |||
| 55d600c0c0 | |||
| 71c5bd5e6c | |||
| 998f04713f | |||
| 6935fbea8b | |||
| 301e090251 | |||
| 58d8ef050c | |||
| 41cb2ec791 | |||
| 1faec5b2d1 | |||
| 111b8cec97 | |||
| 3aaebdb1c4 | |||
| 3e7b8c93e3 | |||
| 3e2f46377e | |||
| 38bead3dc8 | |||
| 351d36b217 | |||
| 59a37c9b46 | |||
| d7d3722ce7 | |||
| 6475524d23 | |||
| 1a70ca9564 | |||
| d6f206f0bb | |||
| b3c5366f31 | |||
| fab06ca4d5 | |||
| bd1d04943d | |||
| 8305d1b0c5 | |||
| 2d812c03eb | |||
| 156e63fd6c | |||
| a912c4dc55 | |||
| 8a2a68a91c | |||
| 01d3ab1357 | |||
| 20c5af7a69 | |||
| 865311bf49 | |||
| 9fab06795a | |||
| 038fb7ae76 | |||
| 3775e0dd7b | |||
| 66a5d69846 | |||
| 8747f887f8 | |||
| 39f4460e0a | |||
| 6f8626ca8a | |||
| 04c08bf419 | |||
| 709a24366a | |||
| 63dad8c626 | |||
| b57342f53e | |||
| 7cefa3a650 | |||
| 5d54ae898e | |||
| 794d5c2dad | |||
| 04cdf1bd2f | |||
| b4c4e31437 | |||
| 56bb321e4a | |||
| c0d868088e | |||
| df5c89f071 | |||
| b73bc3e80a | |||
| db25b2bfbb | |||
| 819bfc1531 | |||
| cfdb8d8474 | |||
| d50ed9858c | |||
| 7af4b6a5d1 | |||
| ca04f5d8c3 | |||
| a02cefc62a | |||
| 28974e9688 | |||
| aaf5f79895 | |||
| eccac4d4a2 | |||
| 399f67ba25 | |||
| 439a580dfe | |||
| bfae290927 | |||
| 1eeb0b7102 | |||
| f49ac19af1 | |||
| 27c85ff9d0 | |||
| b6d44b5a20 | |||
| b8b7574536 | |||
| 5ee2cb2b56 | |||
| 6c88bc1790 | |||
| 6be832b012 | |||
| fc9ef6b9ff | |||
| ec19103a81 | |||
| 7499a21cbd | |||
| 5758b3a320 | |||
| 7d2f818fca | |||
| 19d0946e06 | |||
| 7d5294e7b9 | |||
| 28ed3fcf74 | |||
| 5a35cd04a6 | |||
| 5648224062 | |||
| bbb9cacd71 | |||
| 40743442e9 | |||
| 7564c5d740 | |||
| 3a6d5bb8c4 | |||
| f256ca7fad | |||
| cb18e436ca | |||
| 019b1166ec | |||
| cc15f27205 | |||
| 356c049aaf | |||
| df6465fa8a | |||
| a05c33ad87 | |||
| 67906cbf16 | |||
| 09e381ecc4 | |||
| 7fd35b79c4 | |||
| c9900e4314 | |||
| 5ea3bac570 | |||
| eae7bb0e09 | |||
| 465daec0ab | |||
| f516f46b06 | |||
| 742d0172cf | |||
| e0568ddfdc | |||
| 9941dfa61f | |||
| aac9e9f38f | |||
| bdda87778c | |||
| fccec6d87c | |||
| 5e259e0b42 | |||
| 496c483050 | |||
| 1433f88d53 | |||
| 506c4f9357 | |||
| a4ed475237 | |||
| de43e917c5 | |||
| be515979cf | |||
| cc03069d57 | |||
| fe7aaadf64 | |||
| 0b6549a359 | |||
| af60555eea | |||
| 64334192de | |||
| 4751fb5582 | |||
| 34e56a13ea | |||
| c3f2603702 | |||
| 15f6b2edd0 | |||
| 6339b733c4 | |||
| 305ce21e41 | |||
| 8ab1c91b38 | |||
| bf5c7a74cb | |||
| b48ec98cb3 | |||
| 58089e558e | |||
| 97b6874258 | |||
| 8ad0c4d336 | |||
| 536fc2b463 | |||
| b7287b0d51 | |||
| a0ffb52f98 | |||
| eb40b7ff06 | |||
| b3a71cb9bc | |||
| 16594b3e7d | |||
| 7937e00018 | |||
| 0e91e1e7f5 | |||
| 99b387fe8b | |||
| fe53ea7551 | |||
| 541f9b3776 | |||
| 1c9302c773 | |||
| ba9ef3913d | |||
| 79b4a615f0 | |||
| 7225a5e787 | |||
| 467ade9340 | |||
| 619136674e | |||
| 3990566fe5 | |||
| 7f01dc4cac | |||
| da95b2fa71 | |||
| 9b628caaef | |||
| 4ec924b736 | |||
| 2712bd2197 | |||
| 03d3ff5712 | |||
| 6aeb0c9f89 | |||
| 91394ef68a | |||
| a7d304cc5b | |||
| 0b8619bf64 | |||
| 30e75d0ad5 | |||
| a18a0e913d | |||
| ecf3e03e81 | |||
| 934471bd88 | |||
| 0fff2f87a5 | |||
| e8bf13275e | |||
| 436903543b | |||
| c47f678220 | |||
| d4438c8585 | |||
| 0df4a4c1ec | |||
| 365d15767b | |||
| 4969520222 | |||
| 9cfd7f5052 | |||
| faad280aa0 | |||
| f1ea4b9b20 | |||
| b6b90bca7d | |||
| 39b9726be7 | |||
| 7fc3c3db63 | |||
| 89b2a1cf45 | |||
| 94ee6bc9a4 | |||
| 81f04c6c51 | |||
| d0c67baeb8 | |||
| 35fa61ef34 | |||
| 8b5fb0861d | |||
| 17a3602d3c | |||
| fa42667c2a | |||
| d161d5f421 | |||
| a36b1e8310 | |||
| 640ad93684 | |||
| 51a3a10701 | |||
| cf340ca277 | |||
| c0d51ee06d | |||
| 53d73142ae | |||
| 8e52274edd | |||
| cbde498ae8 | |||
| 9feace9558 | |||
| 2a5496118b | |||
| f362b2ab77 | |||
| 7a8cd490d5 | |||
| 5a20d97084 | |||
| 8def0af08f | |||
| 348d8e1d03 | |||
| a078503a89 | |||
| bc57914131 | |||
| 3b01625f7d | |||
| 8cf4762a65 | |||
| 6f9b384caa | |||
| 7ac54dd987 | |||
| 57684db260 | |||
| c20998d365 | |||
| 2f1d88b001 | |||
| b8453eaf43 | |||
| 87d22fba6d | |||
| e4eb5c80fc | |||
| c8e3542fe8 | |||
| 0ac30a5190 | |||
| c02651e65a | |||
| 9a5a28098c | |||
| 9cfc423a38 | |||
| 3b043eaf6d | |||
| 386b70314d | |||
| e2add63337 | |||
| 7de9b583d5 | |||
| 406c0f539e | |||
| 1651b8a550 | |||
| ff2fdd3c08 | |||
| 35ad68fbbe | |||
| bd4503c035 | |||
| c423af5498 | |||
| a2d482e16d | |||
| 12ef36af33 | |||
| 6ae6c5e0e5 | |||
| 44b47ce18c | |||
| c96c24f864 | |||
| df50e70f3e | |||
| da669efee2 | |||
| 776346ca19 | |||
| af8dd30afe | |||
| 5599bfad67 | |||
| 83d1e7677a | |||
| 16d91bac8f | |||
| 1c4cc1e393 | |||
| 03eaa38a08 | |||
| 640d2affa8 | |||
| bd9f1ce260 | |||
| 1746412a11 | |||
| 7ec31696fc | |||
| 96d26c5431 | |||
| 21d2e34025 | |||
| 5941526a5e | |||
| e15cb70bdc | |||
| 18312e12a9 | |||
| 033fe672df | |||
| b46fed0624 | |||
| c3d40022df | |||
| 0e81fa3bc9 | |||
| cdbe1f1083 | |||
| c0e2d93c49 | |||
| c9a024840b | |||
| d8db7df64e | |||
| ef8f774f4f | |||
| fa0a61f581 | |||
| addb5d7383 | |||
| 3aa2d3d3c8 | |||
| 7bbd895115 |
106
.chatgpt_config.yaml
Normal file
106
.chatgpt_config.yaml
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
project_name: "cloonar-nixos"
|
||||||
|
default_prompt_blocks:
|
||||||
|
- "basic-prompt"
|
||||||
|
- "secure-coding"
|
||||||
|
initial_prompt: |
|
||||||
|
You are helping me build or refine a NixOS configuration (potentially with Nix Flakes). Please keep the following points in mind when generating or explaining code:
|
||||||
|
|
||||||
|
1. **Project & Directory Structure**
|
||||||
|
- For single-host configurations, you may have a simple structure like:
|
||||||
|
```
|
||||||
|
/etc/nixos/
|
||||||
|
├── configuration.nix
|
||||||
|
├── hardware-configuration.nix
|
||||||
|
└── other-module.nix
|
||||||
|
```
|
||||||
|
- For multi-host setups or more complex deployments, consider **modules** in a dedicated folder:
|
||||||
|
```
|
||||||
|
my-nix-config/
|
||||||
|
├── flake.nix # (if using Flakes)
|
||||||
|
├── hosts/
|
||||||
|
│ ├── hostname1/
|
||||||
|
│ │ └── configuration.nix
|
||||||
|
│ └── hostname2/
|
||||||
|
│ └── configuration.nix
|
||||||
|
├── modules/
|
||||||
|
│ ├── networking.nix
|
||||||
|
│ ├── services.nix
|
||||||
|
│ ├── users.nix
|
||||||
|
│ └── ...
|
||||||
|
└── hardware/
|
||||||
|
└── hardware-configuration-<machine>.nix
|
||||||
|
```
|
||||||
|
- Split large configurations into multiple `.nix` files or modules for clarity. Import them in a top-level `configuration.nix` or `flake.nix`.
|
||||||
|
|
||||||
|
2. **Nix Flakes (Optional)**
|
||||||
|
- If using Flakes, include a top-level `flake.nix` defining your outputs:
|
||||||
|
- `outputs.nixosConfigurations.<hostname> = { ... }`
|
||||||
|
- Reference your system with something like `nixos-rebuild switch --flake .#<hostname>`.
|
||||||
|
- Keep pinned inputs (e.g., `nixpkgs` at a particular commit) in your `flake.lock` to ensure reproducibility.
|
||||||
|
|
||||||
|
3. **System Configuration & Modules**
|
||||||
|
- Place typical NixOS settings (e.g., `networking.hostName`, `time.timeZone`, `environment.systemPackages`, etc.) in `configuration.nix` or a modular file structure.
|
||||||
|
- Use [NixOS modules](https://nixos.org/manual/nixos/stable/index.html#sec-writing-modules) to separate concerns. For example:
|
||||||
|
- `networking.nix` for network settings,
|
||||||
|
- `users.nix` for user/group management,
|
||||||
|
- `services.nix` for enabling/configuring system services.
|
||||||
|
- If you have custom logic or package overlays, keep them in separate files (e.g., `overlays.nix`).
|
||||||
|
|
||||||
|
4. **Home Manager Integration (Optional)**
|
||||||
|
- For user-level configuration (e.g., dotfiles, user-specific packages), consider integrating [Home Manager](https://nix-community.github.io/home-manager/) either as a standalone or via Flakes.
|
||||||
|
- Keep Home Manager configs in a separate `home.nix` file, referencing it in your main configuration or flake outputs.
|
||||||
|
|
||||||
|
5. **Security & Secrets Management**
|
||||||
|
- Avoid committing plain-text secrets (passwords, tokens) to version control.
|
||||||
|
- Consider using [sops-nix](https://github.com/Mic92/sops-nix) or other secret management solutions to encrypt sensitive files.
|
||||||
|
- Enable recommended security settings, such as:
|
||||||
|
- `security.sudo.wheelNeedsPassword = true`
|
||||||
|
- `security.rtkit.enable = true`
|
||||||
|
- `users.users.<name>.extraGroups` to limit privileges.
|
||||||
|
- Regularly update your `nixpkgs` channel or flake inputs for the latest security patches.
|
||||||
|
|
||||||
|
6. **System Services & Daemons**
|
||||||
|
- Use built-in NixOS modules for services (e.g., `services.nginx`, `services.postgresql`, etc.) instead of manual configuration whenever possible.
|
||||||
|
- For each service, ensure you:
|
||||||
|
- Set `enable = true;` if it’s needed,
|
||||||
|
- Provide configuration in the same module file or a dedicated file if it’s complex.
|
||||||
|
- Keep service-specific secrets (e.g., database passwords) out of the main config by referencing environment variables or a secret management solution.
|
||||||
|
|
||||||
|
7. **Package Management & Overlays**
|
||||||
|
- Place packages you need system-wide into `environment.systemPackages`.
|
||||||
|
- For overriding or extending packages from `nixpkgs`, use the [overlays](https://nixos.wiki/wiki/Overlays) mechanism:
|
||||||
|
```nix
|
||||||
|
self: super: {
|
||||||
|
myPackage = super.callPackage ./pkgs/my-package { };
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- Maintain a dedicated `overlays/` folder if you have multiple custom overlays.
|
||||||
|
|
||||||
|
8. **Customization & Extensions**
|
||||||
|
- Use `environment.etc` or NixOS options to create or manage custom config files in `/etc/`.
|
||||||
|
- For advanced use cases, you can define your own modules to unify logic for related settings or services.
|
||||||
|
- Document each module with comments about what it configures and why.
|
||||||
|
|
||||||
|
9. **Testing & Deployment**
|
||||||
|
- Use the `nixos-rebuild test` command to evaluate changes without fully switching.
|
||||||
|
- If using Flakes, run `nixos-rebuild test --flake .#<hostname>`.
|
||||||
|
- Test critical services after switching (e.g., `systemctl status service-name`).
|
||||||
|
- Consider building virtual machines via `nixos-rebuild build-vm` or [NixOS tests](https://nixos.org/manual/nixos/stable/index.html#sec-nixos-tests) to validate complex changes.
|
||||||
|
|
||||||
|
10. **Output Format**
|
||||||
|
- Present any generated Nix configuration as well-structured `.nix` files, referencing them in a central place (`configuration.nix` or `flake.nix`).
|
||||||
|
- When explaining your reasoning, describe which modules or options you chose and why (e.g., “I separated `networking.nix` to isolate network settings from system services.”).
|
||||||
|
- If you modify existing files, specify precisely which lines or sections have changed, and why you made those changes.
|
||||||
|
|
||||||
|
Please follow these guidelines to ensure the generated or explained NixOS configuration adheres to best practices for maintainability, modularity, and security.
|
||||||
|
|
||||||
|
debug: false
|
||||||
|
improved_debug: false
|
||||||
|
|
||||||
|
preview_changes: false
|
||||||
|
interactive_file_selection: false
|
||||||
|
partial_acceptance: false
|
||||||
|
|
||||||
|
enable_debug_commands: false
|
||||||
|
prompt_char_limit: 300000
|
||||||
|
enable_step_by_step: true
|
||||||
1
.github/copilot-instructions.md
vendored
Symbolic link
1
.github/copilot-instructions.md
vendored
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../.roo/rules/rules.md
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -3,3 +3,6 @@
|
|||||||
|
|
||||||
raspberry/.env
|
raspberry/.env
|
||||||
raspberry/result
|
raspberry/result
|
||||||
|
|
||||||
|
esphome/trash
|
||||||
|
esphome/.esphome
|
||||||
|
|||||||
8
.mcp.json
Normal file
8
.mcp.json
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"nixos": {
|
||||||
|
"command": "uvx",
|
||||||
|
"args": ["mcp-nixos"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
84
.roo/rules/rules.md
Normal file
84
.roo/rules/rules.md
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
# RULES.md
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This repository manages NixOS configurations for multiple systems, structured to promote modularity, security, and maintainability.
|
||||||
|
|
||||||
|
### Directory Structure
|
||||||
|
|
||||||
|
Each host has its own directory under `hosts/`, containing:
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
hosts/
|
||||||
|
└── hostname/
|
||||||
|
├── configuration.nix
|
||||||
|
├── modules/
|
||||||
|
└── secrets.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
* `configuration.nix`: Main configuration file for the host.
|
||||||
|
* `modules/`: Custom NixOS modules specific to the host.
|
||||||
|
* `secrets.yaml`: Encrypted secrets file (see [Secrets Management](#secrets-management)).
|
||||||
|
|
||||||
|
## Configuration Management
|
||||||
|
|
||||||
|
### Modularization
|
||||||
|
|
||||||
|
* Break down configurations into reusable modules placed in the `modules/` directory.
|
||||||
|
* Use the `imports` directive in `configuration.nix` to include necessary modules.
|
||||||
|
* Avoid monolithic configurations; modularity enhances clarity and reusability.
|
||||||
|
|
||||||
|
### Version Control
|
||||||
|
|
||||||
|
* Track all configuration files using Git.
|
||||||
|
* Exclude sensitive files like `secrets.yaml` from version control.
|
||||||
|
* Use descriptive commit messages to document changes.
|
||||||
|
|
||||||
|
## Deployment with Bento
|
||||||
|
|
||||||
|
Bento is utilized for deploying configurations across systems.
|
||||||
|
|
||||||
|
* Centralize configurations on a management server.
|
||||||
|
* Ensure each host accesses only its specific configuration files.
|
||||||
|
* Leverage Bento's features to manage deployments efficiently.([NixOS Discourse][1], [Reddit][2], [cbiit.github.io][3])
|
||||||
|
|
||||||
|
## Security Best Practices
|
||||||
|
|
||||||
|
### Secrets Management
|
||||||
|
|
||||||
|
* Never store plain-text secrets in the Nix store or configuration files.
|
||||||
|
* Use tools like [sops-nix](https://github.com/Mic92/sops-nix) to encrypt `secrets.yaml`.
|
||||||
|
* Restrict access to decrypted secrets using appropriate file permissions.([Reddit][4], [dade][5])
|
||||||
|
|
||||||
|
### System Hardening
|
||||||
|
|
||||||
|
* Disable unnecessary services to minimize attack surfaces.
|
||||||
|
* Configure firewalls to allow only essential traffic.
|
||||||
|
* Regularly update systems to apply security patches.
|
||||||
|
|
||||||
|
### User Management
|
||||||
|
|
||||||
|
* Implement the principle of least privilege for user accounts.
|
||||||
|
* Use SSH keys for authentication; disable password-based logins.
|
||||||
|
* Monitor user activities and access logs for suspicious behavior.
|
||||||
|
|
||||||
|
## Maintenance Guidelines
|
||||||
|
|
||||||
|
* Regularly review and refactor modules for efficiency and clarity.
|
||||||
|
* Document all modules and configurations for future reference.
|
||||||
|
* Test configurations in a controlled environment before deploying to production systems.([NixOS & Flakes][6])
|
||||||
|
* After developing a feature, delete the corresponding development plan.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Adhering to these guidelines will help maintain a secure, organized, and efficient NixOS configuration across multiple systems.
|
||||||
|
|
||||||
|
[1]: https://discourse.nixos.org/t/introducing-bento-a-nixos-deployment-framework/21446?utm_source=chatgpt.com "Introducing bento, a NixOS deployment framework"
|
||||||
|
[2]: https://www.reddit.com/r/NixOS/comments/1e95b69/how_do_you_guys_organize_your_nix_config_files_i/?utm_source=chatgpt.com "How do you guys organize your .nix config files? I have a ... - Reddit"
|
||||||
|
[3]: https://cbiit.github.io/bento-docs/master/installation/bento-quick-start.html?utm_source=chatgpt.com "1. Quick Start Tutorial — Bento release-4.1.0 documentation"
|
||||||
|
[4]: https://www.reddit.com/r/NixOS/comments/1cnhx6z/best_security_practices_for_nixos_devices_exposed/?utm_source=chatgpt.com "Best Security practices for NixOS devices exposed to the Internet"
|
||||||
|
[5]: https://0xda.de/blog/2024/07/framework-and-nixos-sops-nix-secrets-management/?utm_source=chatgpt.com "Framework and NixOS - Sops-nix Secrets Management - dade"
|
||||||
|
[6]: https://nixos-and-flakes.thiscute.world/nixos-with-flakes/modularize-the-configuration?utm_source=chatgpt.com "Modularize Your NixOS Configuration | NixOS & Flakes Book"
|
||||||
100
.sops.yaml
100
.sops.yaml
@@ -4,21 +4,20 @@
|
|||||||
# for a more complex example.
|
# for a more complex example.
|
||||||
keys:
|
keys:
|
||||||
- &bitwarden age14grjcxaq4h55yfnjxvnqhtswxhj9sfdcvyas4lwvpa8py27pjy2sv3g6v7 # nixos age key
|
- &bitwarden age14grjcxaq4h55yfnjxvnqhtswxhj9sfdcvyas4lwvpa8py27pjy2sv3g6v7 # nixos age key
|
||||||
- &dominik age16veg3fmvpfm7a89a9fc8dvvsxmsthlm70nfxqspr6t8vnf9wkcwsvdq38d
|
- &dominik age1exny8unxynaw03yu8ppahu5z28uermghr8ag34e7kdqnaduq9stsyettzz
|
||||||
- &dominik2 age1v6p8dan2t3w9h94fz4flldl32082j3s9x6zqq7u5j66keth9aphsd6pvch
|
- &dominik2 age1v6p8dan2t3w9h94fz4flldl32082j3s9x6zqq7u5j66keth9aphsd6pvch
|
||||||
- &git-server age106n5n3rrrss45eqqzz8pq90la3kqdtnw63uw0sfa2mahk5xpe30sxs5x58
|
- &git-server age106n5n3rrrss45eqqzz8pq90la3kqdtnw63uw0sfa2mahk5xpe30sxs5x58
|
||||||
- &web-01-server age1y6lvl5jkwc47p5ae9yz9j9kuwhy7rtttua5xhygrgmr7ehd49svsszyt42
|
|
||||||
- &web-02 age1gjm4c3swt8u88e36gf2qlg3syxfc0ly94u64c42f2tsf24npw4csa6e4fw
|
- &web-02 age1gjm4c3swt8u88e36gf2qlg3syxfc0ly94u64c42f2tsf24npw4csa6e4fw
|
||||||
- &web-arm age1ylrpaytkm0k5kcecsxvyv5xd9ts4md0uap48g6wsmj9pwm4lf5esffu0gw
|
- &web-arm age1ylrpaytkm0k5kcecsxvyv5xd9ts4md0uap48g6wsmj9pwm4lf5esffu0gw
|
||||||
- &home-assistant-server age1ezq2j34qngky22enhnslx6hzh4ekwk8dtmn6c9us0uqxqpn7hgpsspjz58
|
|
||||||
- &ldap-server-test age1azmxsw5llmp2nnsv3yc2l8paelmq9rfepxd8jvmswgsmax0qyyxqdnsc7t
|
|
||||||
- &testmodules age1zkzpnfeakyvg3fqtyay32sushjx2hqe28y6hs6ss7plemzqjqa5s6s5yu3
|
|
||||||
- &ldap-server-arm age1jyeppc8yl2twnv8fwcewutd5gjewnxl59lmhev6ygds9qel8zf8syt7zz4
|
- &ldap-server-arm age1jyeppc8yl2twnv8fwcewutd5gjewnxl59lmhev6ygds9qel8zf8syt7zz4
|
||||||
- &fw age1wq82xjyj80htz33x7agxddjfumr3wkwh3r24tasagepxw7ka893sau68df
|
- &fw age1wq82xjyj80htz33x7agxddjfumr3wkwh3r24tasagepxw7ka893sau68df
|
||||||
- &fw-new age12msc2c6drsaw0yk2hjlaw0q0lyq0emjx5e8rq7qc7ql689k593kqfmhss2
|
- &fw-new age12msc2c6drsaw0yk2hjlaw0q0lyq0emjx5e8rq7qc7ql689k593kqfmhss2
|
||||||
- &netboot age14uarclad0ty5supc8ep09793xrnwkv8a4h9j0fq8d8lc92n2dadqkf64vw
|
- &netboot age14uarclad0ty5supc8ep09793xrnwkv8a4h9j0fq8d8lc92n2dadqkf64vw
|
||||||
|
- &gpd-win4 age1ceg548u5ma6rgu3xgvd254y5xefqrdqfqhcjsjp3255q976fgd2qaua53d
|
||||||
|
- &nb age1exny8unxynaw03yu8ppahu5z28uermghr8ag34e7kdqnaduq9stsyettzz
|
||||||
|
- &amzebs-01 age1xcgc6u7fmc2trgxtdtf5nhrd7axzweuxlg0ya9jre3sdrg6c6easecue9w
|
||||||
|
- &nas age1x3elhtccp4u8ha5ry32juj9fkpg0qg7qqx4gduuehgwwnnhcxp8s892hek
|
||||||
|
|
||||||
- &mail-social-grow-tech age1gtulvdj4aclpfhk3mmzvpz9xysccxhvu99x6ayaqlj8m44ehffgq6zuc5u
|
|
||||||
creation_rules:
|
creation_rules:
|
||||||
- path_regex: ^[^/]+\.yaml$
|
- path_regex: ^[^/]+\.yaml$
|
||||||
key_groups:
|
key_groups:
|
||||||
@@ -26,24 +25,29 @@ creation_rules:
|
|||||||
- *bitwarden
|
- *bitwarden
|
||||||
- *dominik
|
- *dominik
|
||||||
- *dominik2
|
- *dominik2
|
||||||
- path_regex: hosts/nb-01.cloonar.com/[^/]+\.yaml$
|
- *nb
|
||||||
|
- path_regex: hosts/nb/[^/]+\.yaml$
|
||||||
key_groups:
|
key_groups:
|
||||||
- age:
|
- age:
|
||||||
- *bitwarden
|
- *bitwarden
|
||||||
- *dominik
|
- *dominik
|
||||||
- *dominik2
|
- *dominik2
|
||||||
- path_regex: hosts/nb-new.cloonar.com/[^/]+\.yaml$
|
- *nb
|
||||||
|
- path_regex: hosts/gpd-win4/[^/]+\.yaml$
|
||||||
key_groups:
|
key_groups:
|
||||||
- age:
|
- age:
|
||||||
- *bitwarden
|
- *bitwarden
|
||||||
- *dominik
|
- *dominik
|
||||||
- *dominik2
|
- *dominik2
|
||||||
- path_regex: hosts/fw.cloonar.com/[^/]+\.yaml$
|
- *gpd-win4
|
||||||
|
- *nb
|
||||||
|
- path_regex: hosts/fw/[^/]+\.yaml$
|
||||||
key_groups:
|
key_groups:
|
||||||
- age:
|
- age:
|
||||||
- *bitwarden
|
- *bitwarden
|
||||||
- *dominik
|
- *dominik
|
||||||
- *dominik2
|
- *dominik2
|
||||||
|
- *nb
|
||||||
- *fw
|
- *fw
|
||||||
- path_regex: hosts/fw-new/[^/]+\.yaml$
|
- path_regex: hosts/fw-new/[^/]+\.yaml$
|
||||||
key_groups:
|
key_groups:
|
||||||
@@ -51,110 +55,102 @@ creation_rules:
|
|||||||
- *bitwarden
|
- *bitwarden
|
||||||
- *dominik
|
- *dominik
|
||||||
- *dominik2
|
- *dominik2
|
||||||
|
- *nb
|
||||||
|
- *fw
|
||||||
- *fw-new
|
- *fw-new
|
||||||
- path_regex: hosts/fw.cloonar.com/modules/web/[^/]+\.yaml$
|
- path_regex: hosts/fw-new/modules/web/[^/]+\.yaml$
|
||||||
key_groups:
|
|
||||||
- age:
|
|
||||||
- *bitwarden
|
|
||||||
- *dominik
|
|
||||||
- *web-02
|
|
||||||
- path_regex: hosts/web-01.cloonar.com/[^/]+\.yaml$
|
|
||||||
key_groups:
|
key_groups:
|
||||||
- age:
|
- age:
|
||||||
- *bitwarden
|
- *bitwarden
|
||||||
- *dominik
|
- *dominik
|
||||||
- *dominik2
|
- *dominik2
|
||||||
- *web-01-server
|
- *web-02
|
||||||
- path_regex: hosts/web-arm/[^/]+\.yaml$
|
- path_regex: hosts/web-arm/[^/]+\.yaml$
|
||||||
key_groups:
|
key_groups:
|
||||||
- age:
|
- age:
|
||||||
- *bitwarden
|
- *bitwarden
|
||||||
- *dominik
|
- *dominik
|
||||||
- *dominik2
|
- *dominik2
|
||||||
|
- *nb
|
||||||
- *web-arm
|
- *web-arm
|
||||||
- path_regex: hosts/mail.cloonar.com/[^/]+\.yaml$
|
- path_regex: hosts/amzebs-01/[^/]+\.yaml$
|
||||||
key_groups:
|
key_groups:
|
||||||
- age:
|
- age:
|
||||||
- *bitwarden
|
- *bitwarden
|
||||||
- *dominik
|
- *dominik
|
||||||
- *dominik2
|
- *dominik2
|
||||||
|
- *nb
|
||||||
|
- *amzebs-01
|
||||||
|
- path_regex: hosts/nas/[^/]+\.yaml$
|
||||||
|
key_groups:
|
||||||
|
- age:
|
||||||
|
- *bitwarden
|
||||||
|
- *dominik
|
||||||
|
- *dominik2
|
||||||
|
- *nb
|
||||||
|
- *nas
|
||||||
|
- path_regex: hosts/mail/[^/]+\.yaml$
|
||||||
|
key_groups:
|
||||||
|
- age:
|
||||||
|
- *bitwarden
|
||||||
|
- *dominik
|
||||||
|
- *dominik2
|
||||||
|
- *nb
|
||||||
- *ldap-server-arm
|
- *ldap-server-arm
|
||||||
- *ldap-server-test
|
- path_regex: hosts/fw/modules/web/[^/]+\.yaml$
|
||||||
- path_regex: hosts/mail.social-grow.tech/[^/]+\.yaml$
|
|
||||||
key_groups:
|
key_groups:
|
||||||
- age:
|
- age:
|
||||||
- *bitwarden
|
- *bitwarden
|
||||||
- *dominik
|
- *dominik
|
||||||
- *dominik2
|
- *dominik2
|
||||||
- *mail-social-grow-tech
|
- *nb
|
||||||
|
- *web-02
|
||||||
- path_regex: utils/modules/lego/[^/]+\.yaml$
|
- path_regex: utils/modules/lego/[^/]+\.yaml$
|
||||||
key_groups:
|
key_groups:
|
||||||
- age:
|
- age:
|
||||||
- *bitwarden
|
- *bitwarden
|
||||||
- *dominik
|
- *dominik
|
||||||
- *dominik2
|
- *dominik2
|
||||||
|
- *nb
|
||||||
- *git-server
|
- *git-server
|
||||||
- *web-01-server
|
|
||||||
- *web-02
|
- *web-02
|
||||||
- *web-arm
|
- *web-arm
|
||||||
- *home-assistant-server
|
|
||||||
- *ldap-server-arm
|
- *ldap-server-arm
|
||||||
- *ldap-server-test
|
|
||||||
- *testmodules
|
|
||||||
- *netboot
|
- *netboot
|
||||||
- *fw
|
- *fw
|
||||||
- *fw-new
|
- *fw-new
|
||||||
- *mail-social-grow-tech
|
- path_regex: utils/modules/attic-cache/[^/]+\.yaml$
|
||||||
- path_regex: hosts/web-01.cloonar.com/modules/bitwarden/[^/]+\.yaml$
|
|
||||||
key_groups:
|
key_groups:
|
||||||
- age:
|
- age:
|
||||||
- *bitwarden
|
- *bitwarden
|
||||||
- *dominik
|
- *dominik
|
||||||
- *dominik2
|
- *dominik2
|
||||||
- *web-01-server
|
- *nb
|
||||||
- path_regex: hosts/web-01.cloonar.com/modules/zammad/[^/]+\.yaml$
|
|
||||||
key_groups:
|
|
||||||
- age:
|
|
||||||
- *bitwarden
|
|
||||||
- *dominik
|
|
||||||
- *dominik2
|
|
||||||
- *web-01-server
|
|
||||||
- path_regex: utils/modules/plausible/[^/]+\.yaml$
|
|
||||||
key_groups:
|
|
||||||
- age:
|
|
||||||
- *bitwarden
|
|
||||||
- *dominik
|
|
||||||
- *dominik2
|
|
||||||
- *web-01-server
|
|
||||||
- path_regex: utils/modules/promtail/[^/]+\.yaml$
|
- path_regex: utils/modules/promtail/[^/]+\.yaml$
|
||||||
key_groups:
|
key_groups:
|
||||||
- age:
|
- age:
|
||||||
- *bitwarden
|
- *bitwarden
|
||||||
- *dominik
|
- *dominik
|
||||||
- *dominik2
|
- *dominik2
|
||||||
- *git-server
|
- *nb
|
||||||
- *web-01-server
|
|
||||||
- *web-arm
|
- *web-arm
|
||||||
- *home-assistant-server
|
|
||||||
- *ldap-server-arm
|
- *ldap-server-arm
|
||||||
- *ldap-server-test
|
|
||||||
- *testmodules
|
|
||||||
- *netboot
|
- *netboot
|
||||||
- *fw
|
- *fw
|
||||||
- *fw-new
|
- *fw-new
|
||||||
|
- *nas
|
||||||
|
- *amzebs-01
|
||||||
- path_regex: utils/modules/victoriametrics/[^/]+\.yaml$
|
- path_regex: utils/modules/victoriametrics/[^/]+\.yaml$
|
||||||
key_groups:
|
key_groups:
|
||||||
- age:
|
- age:
|
||||||
- *bitwarden
|
- *bitwarden
|
||||||
- *dominik
|
- *dominik
|
||||||
- *dominik2
|
- *dominik2
|
||||||
- *git-server
|
- *nb
|
||||||
- *web-01-server
|
|
||||||
- *web-arm
|
- *web-arm
|
||||||
- *home-assistant-server
|
|
||||||
- *ldap-server-arm
|
- *ldap-server-arm
|
||||||
- *ldap-server-test
|
|
||||||
- *testmodules
|
|
||||||
- *netboot
|
- *netboot
|
||||||
- *fw
|
- *fw
|
||||||
- *fw-new
|
- *fw-new
|
||||||
|
- *nas
|
||||||
|
- *amzebs-01
|
||||||
|
|||||||
31
AGENTS.md
Normal file
31
AGENTS.md
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# Repository Guidelines
|
||||||
|
|
||||||
|
## Project Structure & Module Organization
|
||||||
|
- `hosts/<host>/configuration.nix` defines each machine; host modules, packages, and site configs live alongside for composability.
|
||||||
|
- Shared building blocks sit in `utils/` (`modules/`, `overlays/`, `pkgs/`, `bento.nix`), while `fleet.nix` centralizes cross-host user provisioning.
|
||||||
|
- Provisioning assets (ISO profiles, Raspberry Pi imaging, helper scripts) live under `iso/`, `raspberry*/`, and `scripts/`—refer to them before reinventing steps.
|
||||||
|
|
||||||
|
## Build, Test, and Development Commands
|
||||||
|
- Enter the dev shell via `nix-shell` (uses `shell.nix`) to populate MCP helper configs and standard tooling.
|
||||||
|
- Dry-run any change with `./scripts/test-configuration <host>`; append `-v` to mirror `nixos-rebuild --show-trace` for deeper diagnostics.
|
||||||
|
- Deployment relies on the Git runner—once reviewed changes merge to main, the runner rebuilds and switches the relevant host automatically; treat a clean dry-run as the gate before pushing.
|
||||||
|
|
||||||
|
## Coding Style & Naming Conventions
|
||||||
|
- Format Nix files with two-space indentation; run `nixpkgs-fmt` (via `nix run nixpkgs#nixpkgs-fmt .`) before committing complex edits.
|
||||||
|
- Keep module and derivation names in lower kebab-case (`web-arm`, `home-assistant.nix`) and align attribute names with actual host or service identifiers.
|
||||||
|
- Use comments sparingly to justify non-obvious decisions (open ports, unusual service options) and prefer explicit imports over wildcard includes.
|
||||||
|
|
||||||
|
## Testing Guidelines
|
||||||
|
- Always run `./scripts/test-configuration <host>` before raising a PR; it ensures evaluation succeeds and secrets are present.
|
||||||
|
- For service changes, confirm activation with `nixos-rebuild test` (or `switch`) on a staging machine and capture any notable logs.
|
||||||
|
- Document manual smoke checks (e.g., URLs defined in `hosts/web-arm/sites/`) in the PR so reviewers can repeat them quickly.
|
||||||
|
|
||||||
|
## Commit & Pull Request Guidelines
|
||||||
|
- Follow the Conventional Commits pattern used in `git log` (`fix:`, `chore:`, `update:`) and scope by host when helpful (`fix(mail):`).
|
||||||
|
- Split refactors, secrets rotations, and package bumps into distinct commits to simplify review and rollback.
|
||||||
|
- PRs should call out affected hosts, link dry-build output (and confirm the runner result after merge), and tag the owners noted in `hosts/<host>/users/*.nix`; attach screenshots for UI-facing updates.
|
||||||
|
|
||||||
|
## Security & Configuration Tips
|
||||||
|
- Configure `config.sh` before provisioning SFTP users so the values consumed by `fleet.nix` stay in sync with the chroot layout.
|
||||||
|
- Store API keys referenced in `shell.nix` (such as the Brave Search token) under `~/.config/mcp-servers/` and keep real secrets out of version control.
|
||||||
|
- Rotate and edit encrypted `hosts/<host>/secrets.yaml` via `nix-shell -p sops --run 'sops hosts/<host>/secrets.yaml'`; commit only the encrypted output.
|
||||||
100
CLAUDE.md
Normal file
100
CLAUDE.md
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
# CLAUDE.md
|
||||||
|
|
||||||
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||||
|
|
||||||
|
## Repository Overview
|
||||||
|
|
||||||
|
This is a NixOS infrastructure repository managing multiple hosts (servers and personal machines) using a modular Nix configuration approach with SOPS for secrets management and Bento for deployment.
|
||||||
|
|
||||||
|
## Build and Test Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Enter development shell (sets up MCP configs)
|
||||||
|
nix-shell
|
||||||
|
|
||||||
|
# Test configuration before deployment (required before PRs)
|
||||||
|
./scripts/test-configuration <hostname>
|
||||||
|
./scripts/test-configuration -v <hostname> # with --show-trace
|
||||||
|
|
||||||
|
# Edit encrypted secrets
|
||||||
|
nix-shell -p sops --run 'sops hosts/<hostname>/secrets.yaml'
|
||||||
|
|
||||||
|
# Update secrets keys after adding new age keys
|
||||||
|
./scripts/update-secrets-keys
|
||||||
|
|
||||||
|
# Format Nix files
|
||||||
|
nix run nixpkgs#nixpkgs-fmt .
|
||||||
|
|
||||||
|
# Compute hash for new packages
|
||||||
|
nix hash to-sri --type sha256 $(nix-prefetch-url https://example.com/file.tar.gz)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
### Host Structure
|
||||||
|
Each host in `hosts/<hostname>/` contains:
|
||||||
|
- `configuration.nix` - Main entry point importing modules
|
||||||
|
- `hardware-configuration.nix` - Machine-specific hardware config
|
||||||
|
- `secrets.yaml` - SOPS-encrypted secrets
|
||||||
|
- `modules/` - Host-specific service configurations
|
||||||
|
- `fleet.nix` → symlink to root `fleet.nix` (SFTP user provisioning)
|
||||||
|
- `utils/` → symlink to root `utils/` (shared modules)
|
||||||
|
|
||||||
|
Current hosts: `fw` (firewall/router), `nb` (notebook), `web-arm`, `mail`, `amzebs-01`, `nas`
|
||||||
|
|
||||||
|
### Shared Components (`utils/`)
|
||||||
|
- `modules/` - Reusable NixOS modules (nginx, sops, borgbackup, lego, promtail, etc.)
|
||||||
|
- `overlays/` - Nixpkgs overlays
|
||||||
|
- `pkgs/` - Custom package derivations
|
||||||
|
- `bento.nix` - Deployment helper module
|
||||||
|
|
||||||
|
### Secrets Management
|
||||||
|
- SOPS with age encryption; keys defined in `.sops.yaml`
|
||||||
|
- Each host has its own age key derived from SSH host key
|
||||||
|
- Host secrets in `hosts/<hostname>/secrets.yaml`
|
||||||
|
- Shared module secrets in `utils/modules/<module>/secrets.yaml`
|
||||||
|
|
||||||
|
**IMPORTANT: Never modify secrets files directly.** Instead, tell the user which secrets need to be added and where, so they can edit the encrypted files themselves using:
|
||||||
|
```bash
|
||||||
|
nix-shell -p sops --run 'sops hosts/<hostname>/secrets.yaml'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Deployment
|
||||||
|
The Git runner handles deployment automatically when changes merge to main. A successful `./scripts/test-configuration <host>` dry-build is the gate before pushing.
|
||||||
|
|
||||||
|
## Custom Packages
|
||||||
|
|
||||||
|
When creating a new package in `utils/pkgs/`, always include an `update.sh` script to automate version updates. See `utils/pkgs/claude-code/update.sh` for the pattern:
|
||||||
|
|
||||||
|
1. Fetch latest version from upstream (npm, GitHub, etc.)
|
||||||
|
2. Update version string in `default.nix`
|
||||||
|
3. Update source hash using `nix-prefetch-url`
|
||||||
|
4. Update dependency hashes (e.g., `npmDepsHash`) by triggering a build with a fake hash
|
||||||
|
5. Verify the final build succeeds
|
||||||
|
|
||||||
|
Example structure:
|
||||||
|
```
|
||||||
|
utils/pkgs/<package-name>/
|
||||||
|
├── default.nix
|
||||||
|
├── update.sh # Always include this
|
||||||
|
└── (other files like patches, lock files)
|
||||||
|
```
|
||||||
|
|
||||||
|
**IMPORTANT: When modifying a custom package** (patches, version updates, etc.), always test by building the package directly, not just running `test-configuration`. The configuration test only checks that the Nix expression evaluates, but doesn't verify the package actually builds:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build a custom package directly to verify it works
|
||||||
|
nix-build -E 'with import <nixpkgs> { overlays = [ (import ./utils/overlays/packages.nix) ]; config.allowUnfree = true; }; <package-name>'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Workflow
|
||||||
|
|
||||||
|
**IMPORTANT: Always run `./scripts/test-configuration <hostname>` after making any changes** to verify the NixOS configuration builds successfully. This is required before committing.
|
||||||
|
|
||||||
|
## Conventions
|
||||||
|
|
||||||
|
- Nix files: two-space indentation, lower kebab-case naming
|
||||||
|
- Commits: Conventional Commits format (`fix:`, `feat:`, `chore:`), scope by host when relevant (`fix(mail):`). Do not add "Generated with Claude Code" or "Co-Authored-By: Claude" footers.
|
||||||
|
- Modules import via explicit paths, not wildcards
|
||||||
|
- Comments explain non-obvious decisions (open ports, unusual service options)
|
||||||
|
- **Never update `system.stateVersion`** - it should remain at the original installation version. To upgrade NixOS, update the `channel` file instead.
|
||||||
69
README.md
69
README.md
@@ -2,7 +2,8 @@
|
|||||||
- install ubuntu 20.04
|
- install ubuntu 20.04
|
||||||
- get age key from SSH
|
- get age key from SSH
|
||||||
```console
|
```console
|
||||||
nix-shell -p ssh-to-age --run 'ssh-keyscan example.com | ssh-to-age'
|
curl https://raw.githubusercontent.com/elitak/nixos-infect/master/nixos-infect | PROVIDER=hetznercloud NIX_CHANNEL=nixos-25.05 bash 2>&1 | tee /tmp/infect.log
|
||||||
|
nix-shell -p ssh-to-age --run 'ssh-keyscan install.cloonar.com | ssh-to-age'
|
||||||
```
|
```
|
||||||
- fix secrets files
|
- fix secrets files
|
||||||
```console
|
```console
|
||||||
@@ -38,7 +39,7 @@ cat ~/.ssh/id_rsa.pub | ssh -p23 u149513-subx@u149513-subx.your-backup.de instal
|
|||||||
|
|
||||||
# 4. Add new Host
|
# 4. Add new Host
|
||||||
```console
|
```console
|
||||||
sftp host.cloonar.com@git.cloonar.com:/config/bootstrap.sh ./
|
sftp host@git.cloonar.com:/config/bootstrap.sh ./
|
||||||
```
|
```
|
||||||
|
|
||||||
# 5. Yubikey
|
# 5. Yubikey
|
||||||
@@ -52,3 +53,67 @@ systemd-cryptenroll --fido2-device=auto --fido2-with-client-pin=yes /dev/nvme0n1
|
|||||||
wg genkey | (umask 077 && tee privatekey) | wg pubkey > publickey
|
wg genkey | (umask 077 && tee privatekey) | wg pubkey > publickey
|
||||||
umask 0077; wg genpsk > psk
|
umask 0077; wg genpsk > psk
|
||||||
```
|
```
|
||||||
|
|
||||||
|
# 7. Hash for new packages
|
||||||
|
```console
|
||||||
|
nix hash to-sri --type sha256 $(nix-prefetch-url https://tar.gz)
|
||||||
|
```
|
||||||
|
|
||||||
|
# 8. Fingerprint Reader Setup (e.g., on Framework Laptop with Goodix reader)
|
||||||
|
|
||||||
|
This section assumes you have configured fingerprint support in your NixOS configuration, for example, by creating and importing a module like `hosts/nb/modules/fingerprint.nix` with the following content:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
# hosts/nb/modules/fingerprint.nix
|
||||||
|
{ config, pkgs, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
services.fprintd.enable = true;
|
||||||
|
|
||||||
|
security.pam.services.login.fprintAuth = true;
|
||||||
|
security.pam.services.sudo.fprintAuth = true;
|
||||||
|
# Add other services like swaylock if needed
|
||||||
|
# security.pam.services.swaylock.fprintAuth = true;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
After rebuilding your NixOS configuration (`sudo nixos-rebuild switch`), you can enroll fingerprints for a user.
|
||||||
|
|
||||||
|
## Enrolling Fingerprints
|
||||||
|
|
||||||
|
To enroll a fingerprint for the current user:
|
||||||
|
```console
|
||||||
|
fprintd-enroll
|
||||||
|
```
|
||||||
|
Or for a specific user (e.g., `dominik`):
|
||||||
|
```console
|
||||||
|
fprintd-enroll dominik
|
||||||
|
```
|
||||||
|
Follow the on-screen prompts to scan your fingerprint multiple times.
|
||||||
|
|
||||||
|
## Verifying Enrollment
|
||||||
|
You can verify enrolled fingerprints:
|
||||||
|
```console
|
||||||
|
fprintd-verify
|
||||||
|
```
|
||||||
|
|
||||||
|
## Listing Enrolled Fingerprints
|
||||||
|
To see which fingers are enrolled for the current user:
|
||||||
|
```console
|
||||||
|
fprintd-list $(whoami)
|
||||||
|
```
|
||||||
|
Or for a specific user:
|
||||||
|
```console
|
||||||
|
fprintd-list dominik
|
||||||
|
```
|
||||||
|
|
||||||
|
## Deleting Fingerprints
|
||||||
|
To delete all fingerprints for the current user:
|
||||||
|
```console
|
||||||
|
fprintd-delete $(whoami)
|
||||||
|
```
|
||||||
|
Or for a specific user:
|
||||||
|
```console
|
||||||
|
fprintd-delete dominik
|
||||||
|
```
|
||||||
|
You can also delete specific fingerprints by their ID if you know it.
|
||||||
|
|||||||
2
buchhaltung.md
Normal file
2
buchhaltung.md
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Bei EU Rechnungen das Hakerl machen bei "Nicht im Inland steuerbare Leistung (außerhalb EU, z.B. Schweiz)"
|
||||||
|
VXEhGveIHdSj7JKq6zof48vLhKaCo0RJea6DhVqopA8=
|
||||||
5
esphome/.gitignore
vendored
Normal file
5
esphome/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# Gitignore settings for ESPHome
|
||||||
|
# This is an example and may include too much for your use-case.
|
||||||
|
# You can modify this file to suit your needs.
|
||||||
|
/.esphome/
|
||||||
|
/secrets.yaml
|
||||||
9
esphome/README.md
Normal file
9
esphome/README.md
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# Installation
|
||||||
|
OTA Update Shelly Device to tasmota:
|
||||||
|
https://github.com/arendst/mgos-to-tasmota
|
||||||
|
On gen 3 devices just download zip file from below and upload it over the web interface to shelly:
|
||||||
|
https://github.com/tasmota/mgos32-to-tasmota32/releases
|
||||||
|
In Tasmota make OTA Update to minimal:
|
||||||
|
http://ota.tasmota.com/tasmota/release/tasmota-minimal.bin.gz
|
||||||
|
Make ESPHome Configuration in Dashboard:
|
||||||
|
docker run --rm --network host -e ESPHOME_DASHBOARD_USE_PING=true -v "${PWD}":/config -it ghcr.io/esphome/esphome:latest
|
||||||
19
esphome/archive/install.yaml
Normal file
19
esphome/archive/install.yaml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
substitutions:
|
||||||
|
device_name: "install"
|
||||||
|
friendly_name: "Esphome Install"
|
||||||
|
|
||||||
|
esphome:
|
||||||
|
name: ${device_name}
|
||||||
|
comment: ${friendly_name}
|
||||||
|
platform: ESP8266
|
||||||
|
board: esp01_1m
|
||||||
|
|
||||||
|
web_server:
|
||||||
|
port: 80
|
||||||
|
|
||||||
|
ota:
|
||||||
|
platform: esphome
|
||||||
|
|
||||||
|
wifi:
|
||||||
|
ssid: Cloonar-Smart
|
||||||
|
password: 0m6sY7Ue3G31
|
||||||
80
esphome/bathroom-bulb-1.yaml
Normal file
80
esphome/bathroom-bulb-1.yaml
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
substitutions:
|
||||||
|
device_name: "bathroom-bulb-1"
|
||||||
|
friendly_name: "Bathroom Bulb 1"
|
||||||
|
|
||||||
|
esphome:
|
||||||
|
name: ${device_name}
|
||||||
|
comment: ${friendly_name}
|
||||||
|
on_boot:
|
||||||
|
priority: 300
|
||||||
|
then:
|
||||||
|
- light.turn_on:
|
||||||
|
id: my_light
|
||||||
|
- delay: 100ms
|
||||||
|
- light.turn_on:
|
||||||
|
id: my_light
|
||||||
|
brightness: 30%
|
||||||
|
- delay: 100ms
|
||||||
|
- light.turn_on:
|
||||||
|
id: my_light
|
||||||
|
red: 100%
|
||||||
|
green: 50%
|
||||||
|
blue: 0%
|
||||||
|
white: 100%
|
||||||
|
|
||||||
|
esp8266:
|
||||||
|
board: esp01_1m
|
||||||
|
|
||||||
|
interval:
|
||||||
|
- interval: 15s
|
||||||
|
then:
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
api.connected: # check if api connected
|
||||||
|
else:
|
||||||
|
- light.turn_on:
|
||||||
|
id: my_light
|
||||||
|
brightness: 100%
|
||||||
|
|
||||||
|
# Enable Home Assistant API
|
||||||
|
api:
|
||||||
|
batch_delay: 0ms
|
||||||
|
|
||||||
|
ota:
|
||||||
|
platform: esphome
|
||||||
|
|
||||||
|
wifi:
|
||||||
|
ssid: !secret wifi_ssid
|
||||||
|
password: !secret wifi_password
|
||||||
|
fast_connect: True
|
||||||
|
domain: .cloonar.smart
|
||||||
|
|
||||||
|
light:
|
||||||
|
- platform: rgbw
|
||||||
|
id: my_light
|
||||||
|
name: ${friendly_name}
|
||||||
|
red: pwm_r
|
||||||
|
green: pwm_g
|
||||||
|
blue: pwm_b
|
||||||
|
white: pwm_w
|
||||||
|
|
||||||
|
output:
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
pin: GPIO13
|
||||||
|
frequency: 1000 Hz
|
||||||
|
id: pwm_r
|
||||||
|
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
pin: GPIO12
|
||||||
|
frequency: 1000 Hz
|
||||||
|
id: pwm_g
|
||||||
|
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
pin: GPIO14
|
||||||
|
frequency: 1000 Hz
|
||||||
|
id: pwm_b
|
||||||
|
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
pin: GPIO5
|
||||||
|
frequency: 1000 Hz
|
||||||
|
id: pwm_w
|
||||||
80
esphome/bathroom-bulb-2.yaml
Normal file
80
esphome/bathroom-bulb-2.yaml
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
substitutions:
|
||||||
|
device_name: "bathroom-bulb-2"
|
||||||
|
friendly_name: "Bathroom Bulb 2"
|
||||||
|
|
||||||
|
esphome:
|
||||||
|
name: ${device_name}
|
||||||
|
comment: ${friendly_name}
|
||||||
|
on_boot:
|
||||||
|
priority: 300
|
||||||
|
then:
|
||||||
|
- light.turn_on:
|
||||||
|
id: my_light
|
||||||
|
- delay: 100ms
|
||||||
|
- light.turn_on:
|
||||||
|
id: my_light
|
||||||
|
brightness: 30%
|
||||||
|
- delay: 100ms
|
||||||
|
- light.turn_on:
|
||||||
|
id: my_light
|
||||||
|
red: 100%
|
||||||
|
green: 50%
|
||||||
|
blue: 0%
|
||||||
|
white: 100%
|
||||||
|
|
||||||
|
esp8266:
|
||||||
|
board: esp01_1m
|
||||||
|
|
||||||
|
interval:
|
||||||
|
- interval: 15s
|
||||||
|
then:
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
api.connected: # check if api connected
|
||||||
|
else:
|
||||||
|
- light.turn_on:
|
||||||
|
id: my_light
|
||||||
|
brightness: 100%
|
||||||
|
|
||||||
|
# Enable Home Assistant API
|
||||||
|
api:
|
||||||
|
batch_delay: 0ms
|
||||||
|
|
||||||
|
ota:
|
||||||
|
platform: esphome
|
||||||
|
|
||||||
|
wifi:
|
||||||
|
ssid: !secret wifi_ssid
|
||||||
|
password: !secret wifi_password
|
||||||
|
fast_connect: True
|
||||||
|
domain: .cloonar.smart
|
||||||
|
|
||||||
|
light:
|
||||||
|
- platform: rgbw
|
||||||
|
id: my_light
|
||||||
|
name: ${friendly_name}
|
||||||
|
red: pwm_r
|
||||||
|
green: pwm_g
|
||||||
|
blue: pwm_b
|
||||||
|
white: pwm_w
|
||||||
|
|
||||||
|
output:
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
pin: GPIO13
|
||||||
|
frequency: 1000 Hz
|
||||||
|
id: pwm_r
|
||||||
|
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
pin: GPIO12
|
||||||
|
frequency: 1000 Hz
|
||||||
|
id: pwm_g
|
||||||
|
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
pin: GPIO14
|
||||||
|
frequency: 1000 Hz
|
||||||
|
id: pwm_b
|
||||||
|
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
pin: GPIO5
|
||||||
|
frequency: 1000 Hz
|
||||||
|
id: pwm_w
|
||||||
143
esphome/bathroom-switch-1.yaml
Normal file
143
esphome/bathroom-switch-1.yaml
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
substitutions:
|
||||||
|
devicename: bathroom-switch-1
|
||||||
|
# Name for the relays
|
||||||
|
channel_1: Light
|
||||||
|
channel_2: Air
|
||||||
|
max_power: "2000.0" # watt
|
||||||
|
max_temp: "80.0" # °C
|
||||||
|
|
||||||
|
esphome:
|
||||||
|
name: ${devicename}
|
||||||
|
platform: ESP8266
|
||||||
|
board: esp01_1m
|
||||||
|
|
||||||
|
wifi:
|
||||||
|
ssid: !secret wifi_ssid
|
||||||
|
password: !secret wifi_password
|
||||||
|
|
||||||
|
# Enable Home Assistant API
|
||||||
|
api:
|
||||||
|
|
||||||
|
i2c:
|
||||||
|
sda: GPIO12
|
||||||
|
scl: GPIO14
|
||||||
|
|
||||||
|
sensor:
|
||||||
|
- platform: ade7953_i2c
|
||||||
|
voltage:
|
||||||
|
name: ${devicename} voltage
|
||||||
|
current_a:
|
||||||
|
name: ${channel_2} current
|
||||||
|
internal: true
|
||||||
|
current_b:
|
||||||
|
name: ${channel_1} current
|
||||||
|
internal: true
|
||||||
|
active_power_a:
|
||||||
|
name: ${channel_2} power
|
||||||
|
id: power_channel_2
|
||||||
|
filters:
|
||||||
|
- multiply: 1
|
||||||
|
on_value_range:
|
||||||
|
- above: ${max_power}
|
||||||
|
then:
|
||||||
|
- output.turn_off: shelly_25_relay_2
|
||||||
|
- homeassistant.service:
|
||||||
|
service: persistent_notification.create
|
||||||
|
data:
|
||||||
|
title: Message from ${devicename}
|
||||||
|
data_template:
|
||||||
|
message: Switch turned off because power exceeded ${max_power}W
|
||||||
|
active_power_b:
|
||||||
|
name: ${channel_1} power
|
||||||
|
id: power_channel_1
|
||||||
|
filters:
|
||||||
|
- multiply: -1
|
||||||
|
on_value_range:
|
||||||
|
- above: ${max_power}
|
||||||
|
then:
|
||||||
|
- output.turn_off: shelly_25_relay_1
|
||||||
|
- homeassistant.service:
|
||||||
|
service: persistent_notification.create
|
||||||
|
data:
|
||||||
|
title: Message from ${devicename}
|
||||||
|
data_template:
|
||||||
|
message: Switch turned off because power exceeded ${max_power}W
|
||||||
|
update_interval: 30s
|
||||||
|
|
||||||
|
# NTC Temperature
|
||||||
|
- platform: ntc
|
||||||
|
sensor: temp_resistance_reading
|
||||||
|
name: ${devicename} temperature
|
||||||
|
unit_of_measurement: "°C"
|
||||||
|
accuracy_decimals: 1
|
||||||
|
icon: "mdi:thermometer"
|
||||||
|
calibration:
|
||||||
|
b_constant: 3350
|
||||||
|
reference_resistance: 10kOhm
|
||||||
|
reference_temperature: 298.15K
|
||||||
|
on_value_range:
|
||||||
|
- above: ${max_temp}
|
||||||
|
then:
|
||||||
|
- output.turn_off: shelly_25_relay_1
|
||||||
|
- output.turn_off: shelly_25_relay_2
|
||||||
|
- homeassistant.service:
|
||||||
|
service: persistent_notification.create
|
||||||
|
data:
|
||||||
|
title: Message from ${devicename}
|
||||||
|
data_template:
|
||||||
|
message: Switch turned off because temperature exceeded ${max_temp}°C
|
||||||
|
- platform: resistance
|
||||||
|
id: temp_resistance_reading
|
||||||
|
sensor: temp_analog_reading
|
||||||
|
configuration: DOWNSTREAM
|
||||||
|
resistor: 32kOhm
|
||||||
|
- platform: adc
|
||||||
|
id: temp_analog_reading
|
||||||
|
pin: A0
|
||||||
|
|
||||||
|
status_led:
|
||||||
|
pin:
|
||||||
|
number: GPIO0
|
||||||
|
inverted: yes
|
||||||
|
|
||||||
|
output:
|
||||||
|
- platform: gpio
|
||||||
|
pin: GPIO4
|
||||||
|
id: shelly_25_relay_1
|
||||||
|
- platform: gpio
|
||||||
|
pin: GPIO15
|
||||||
|
id: shelly_25_relay_2
|
||||||
|
|
||||||
|
light:
|
||||||
|
- platform: binary
|
||||||
|
name: "${channel_1}"
|
||||||
|
output: shelly_25_relay_1
|
||||||
|
id: lightid
|
||||||
|
- platform: binary
|
||||||
|
name: "${channel_2}"
|
||||||
|
output: shelly_25_relay_2
|
||||||
|
id: airid
|
||||||
|
|
||||||
|
binary_sensor:
|
||||||
|
- platform: gpio
|
||||||
|
pin:
|
||||||
|
number: GPIO13
|
||||||
|
name: "${channel_1} input"
|
||||||
|
internal: true
|
||||||
|
on_state:
|
||||||
|
then:
|
||||||
|
- light.toggle: lightid
|
||||||
|
- platform: gpio
|
||||||
|
pin:
|
||||||
|
number: GPIO5
|
||||||
|
name: "${channel_2} input"
|
||||||
|
internal: true
|
||||||
|
on_state:
|
||||||
|
then:
|
||||||
|
- light.toggle: airid
|
||||||
|
|
||||||
|
# Prevent short circuit with "floating" pin!
|
||||||
|
- platform: gpio
|
||||||
|
pin: GPIO16
|
||||||
|
name: "ade7953 IRQ pin"
|
||||||
|
internal: true
|
||||||
80
esphome/bedroom-bulb-1.yaml
Normal file
80
esphome/bedroom-bulb-1.yaml
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
substitutions:
|
||||||
|
device_name: "bedroom-bulb-1"
|
||||||
|
friendly_name: "Bedroom Bulb 1"
|
||||||
|
|
||||||
|
esphome:
|
||||||
|
name: ${device_name}
|
||||||
|
comment: ${friendly_name}
|
||||||
|
on_boot:
|
||||||
|
priority: 300
|
||||||
|
then:
|
||||||
|
- light.turn_on:
|
||||||
|
id: my_light
|
||||||
|
- delay: 100ms
|
||||||
|
- light.turn_on:
|
||||||
|
id: my_light
|
||||||
|
brightness: 20%
|
||||||
|
- delay: 100ms
|
||||||
|
- light.turn_on:
|
||||||
|
id: my_light
|
||||||
|
red: 100%
|
||||||
|
green: 50%
|
||||||
|
blue: 0%
|
||||||
|
white: 100%
|
||||||
|
|
||||||
|
esp8266:
|
||||||
|
board: esp01_1m
|
||||||
|
|
||||||
|
interval:
|
||||||
|
- interval: 15s
|
||||||
|
then:
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
api.connected: # check if api connected
|
||||||
|
else:
|
||||||
|
- light.turn_on:
|
||||||
|
id: my_light
|
||||||
|
brightness: 100%
|
||||||
|
|
||||||
|
# Enable Home Assistant API
|
||||||
|
api:
|
||||||
|
batch_delay: 0ms
|
||||||
|
|
||||||
|
ota:
|
||||||
|
platform: esphome
|
||||||
|
|
||||||
|
wifi:
|
||||||
|
ssid: !secret wifi_ssid
|
||||||
|
password: !secret wifi_password
|
||||||
|
fast_connect: true
|
||||||
|
domain: .cloonar.smart
|
||||||
|
|
||||||
|
light:
|
||||||
|
- platform: rgbw
|
||||||
|
id: my_light
|
||||||
|
name: ${friendly_name}
|
||||||
|
red: pwm_r
|
||||||
|
green: pwm_g
|
||||||
|
blue: pwm_b
|
||||||
|
white: pwm_w
|
||||||
|
|
||||||
|
output:
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
pin: GPIO13
|
||||||
|
frequency: 1000 Hz
|
||||||
|
id: pwm_r
|
||||||
|
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
pin: GPIO12
|
||||||
|
frequency: 1000 Hz
|
||||||
|
id: pwm_g
|
||||||
|
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
pin: GPIO14
|
||||||
|
frequency: 1000 Hz
|
||||||
|
id: pwm_b
|
||||||
|
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
pin: GPIO5
|
||||||
|
frequency: 1000 Hz
|
||||||
|
id: pwm_w
|
||||||
80
esphome/bedroom-bulb-2.yaml
Normal file
80
esphome/bedroom-bulb-2.yaml
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
substitutions:
|
||||||
|
device_name: "bedroom-bulb-2"
|
||||||
|
friendly_name: "Bedroom Bulb 2"
|
||||||
|
|
||||||
|
esphome:
|
||||||
|
name: ${device_name}
|
||||||
|
comment: ${friendly_name}
|
||||||
|
on_boot:
|
||||||
|
priority: 300
|
||||||
|
then:
|
||||||
|
- light.turn_on:
|
||||||
|
id: my_light
|
||||||
|
- delay: 100ms
|
||||||
|
- light.turn_on:
|
||||||
|
id: my_light
|
||||||
|
brightness: 20%
|
||||||
|
- delay: 100ms
|
||||||
|
- light.turn_on:
|
||||||
|
id: my_light
|
||||||
|
red: 100%
|
||||||
|
green: 50%
|
||||||
|
blue: 0%
|
||||||
|
white: 100%
|
||||||
|
|
||||||
|
esp8266:
|
||||||
|
board: esp01_1m
|
||||||
|
|
||||||
|
interval:
|
||||||
|
- interval: 15s
|
||||||
|
then:
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
api.connected: # check if api connected
|
||||||
|
else:
|
||||||
|
- light.turn_on:
|
||||||
|
id: my_light
|
||||||
|
brightness: 100%
|
||||||
|
|
||||||
|
# Enable Home Assistant API
|
||||||
|
api:
|
||||||
|
batch_delay: 0ms
|
||||||
|
|
||||||
|
ota:
|
||||||
|
platform: esphome
|
||||||
|
|
||||||
|
wifi:
|
||||||
|
ssid: !secret wifi_ssid
|
||||||
|
password: !secret wifi_password
|
||||||
|
fast_connect: True
|
||||||
|
domain: .cloonar.smart
|
||||||
|
|
||||||
|
light:
|
||||||
|
- platform: rgbw
|
||||||
|
id: my_light
|
||||||
|
name: ${friendly_name}
|
||||||
|
red: pwm_r
|
||||||
|
green: pwm_g
|
||||||
|
blue: pwm_b
|
||||||
|
white: pwm_w
|
||||||
|
|
||||||
|
output:
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
pin: GPIO13
|
||||||
|
frequency: 1000 Hz
|
||||||
|
id: pwm_r
|
||||||
|
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
pin: GPIO12
|
||||||
|
frequency: 1000 Hz
|
||||||
|
id: pwm_g
|
||||||
|
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
pin: GPIO14
|
||||||
|
frequency: 1000 Hz
|
||||||
|
id: pwm_b
|
||||||
|
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
pin: GPIO5
|
||||||
|
frequency: 1000 Hz
|
||||||
|
id: pwm_w
|
||||||
80
esphome/bedroom-bulb-3.yaml
Normal file
80
esphome/bedroom-bulb-3.yaml
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
substitutions:
|
||||||
|
device_name: "bedroom-bulb-3"
|
||||||
|
friendly_name: "Bedroom Bulb 3"
|
||||||
|
|
||||||
|
esphome:
|
||||||
|
name: ${device_name}
|
||||||
|
comment: ${friendly_name}
|
||||||
|
on_boot:
|
||||||
|
priority: 300
|
||||||
|
then:
|
||||||
|
- light.turn_on:
|
||||||
|
id: my_light
|
||||||
|
- delay: 100ms
|
||||||
|
- light.turn_on:
|
||||||
|
id: my_light
|
||||||
|
brightness: 20%
|
||||||
|
- delay: 100ms
|
||||||
|
- light.turn_on:
|
||||||
|
id: my_light
|
||||||
|
red: 100%
|
||||||
|
green: 50%
|
||||||
|
blue: 0%
|
||||||
|
white: 100%
|
||||||
|
|
||||||
|
esp8266:
|
||||||
|
board: esp01_1m
|
||||||
|
|
||||||
|
interval:
|
||||||
|
- interval: 15s
|
||||||
|
then:
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
api.connected: # check if api connected
|
||||||
|
else:
|
||||||
|
- light.turn_on:
|
||||||
|
id: my_light
|
||||||
|
brightness: 100%
|
||||||
|
|
||||||
|
# Enable Home Assistant API
|
||||||
|
api:
|
||||||
|
batch_delay: 0ms
|
||||||
|
|
||||||
|
ota:
|
||||||
|
platform: esphome
|
||||||
|
|
||||||
|
wifi:
|
||||||
|
ssid: !secret wifi_ssid
|
||||||
|
password: !secret wifi_password
|
||||||
|
fast_connect: True
|
||||||
|
domain: .cloonar.smart
|
||||||
|
|
||||||
|
light:
|
||||||
|
- platform: rgbw
|
||||||
|
id: my_light
|
||||||
|
name: ${friendly_name}
|
||||||
|
red: pwm_r
|
||||||
|
green: pwm_g
|
||||||
|
blue: pwm_b
|
||||||
|
white: pwm_w
|
||||||
|
|
||||||
|
output:
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
pin: GPIO13
|
||||||
|
frequency: 1000 Hz
|
||||||
|
id: pwm_r
|
||||||
|
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
pin: GPIO12
|
||||||
|
frequency: 1000 Hz
|
||||||
|
id: pwm_g
|
||||||
|
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
pin: GPIO14
|
||||||
|
frequency: 1000 Hz
|
||||||
|
id: pwm_b
|
||||||
|
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
pin: GPIO5
|
||||||
|
frequency: 1000 Hz
|
||||||
|
id: pwm_w
|
||||||
80
esphome/bedroom-bulb-4.yaml
Normal file
80
esphome/bedroom-bulb-4.yaml
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
substitutions:
|
||||||
|
device_name: "bedroom-bulb-4"
|
||||||
|
friendly_name: "Bedroom Bulb 4"
|
||||||
|
|
||||||
|
esphome:
|
||||||
|
name: ${device_name}
|
||||||
|
comment: ${friendly_name}
|
||||||
|
on_boot:
|
||||||
|
priority: 300
|
||||||
|
then:
|
||||||
|
- light.turn_on:
|
||||||
|
id: my_light
|
||||||
|
- delay: 100ms
|
||||||
|
- light.turn_on:
|
||||||
|
id: my_light
|
||||||
|
brightness: 20%
|
||||||
|
- delay: 100ms
|
||||||
|
- light.turn_on:
|
||||||
|
id: my_light
|
||||||
|
red: 100%
|
||||||
|
green: 50%
|
||||||
|
blue: 0%
|
||||||
|
white: 100%
|
||||||
|
|
||||||
|
esp8266:
|
||||||
|
board: esp01_1m
|
||||||
|
|
||||||
|
interval:
|
||||||
|
- interval: 15s
|
||||||
|
then:
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
api.connected: # check if api connected
|
||||||
|
else:
|
||||||
|
- light.turn_on:
|
||||||
|
id: my_light
|
||||||
|
brightness: 100%
|
||||||
|
|
||||||
|
# Enable Home Assistant API
|
||||||
|
api:
|
||||||
|
batch_delay: 0ms
|
||||||
|
|
||||||
|
ota:
|
||||||
|
platform: esphome
|
||||||
|
|
||||||
|
wifi:
|
||||||
|
ssid: !secret wifi_ssid
|
||||||
|
password: !secret wifi_password
|
||||||
|
fast_connect: True
|
||||||
|
domain: .cloonar.smart
|
||||||
|
|
||||||
|
light:
|
||||||
|
- platform: rgbw
|
||||||
|
id: my_light
|
||||||
|
name: ${friendly_name}
|
||||||
|
red: pwm_r
|
||||||
|
green: pwm_g
|
||||||
|
blue: pwm_b
|
||||||
|
white: pwm_w
|
||||||
|
|
||||||
|
output:
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
pin: GPIO13
|
||||||
|
frequency: 1000 Hz
|
||||||
|
id: pwm_r
|
||||||
|
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
pin: GPIO12
|
||||||
|
frequency: 1000 Hz
|
||||||
|
id: pwm_g
|
||||||
|
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
pin: GPIO14
|
||||||
|
frequency: 1000 Hz
|
||||||
|
id: pwm_b
|
||||||
|
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
pin: GPIO5
|
||||||
|
frequency: 1000 Hz
|
||||||
|
id: pwm_w
|
||||||
80
esphome/hallway-bulb-1.yaml
Normal file
80
esphome/hallway-bulb-1.yaml
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
substitutions:
|
||||||
|
device_name: "hallway-bulb-1"
|
||||||
|
friendly_name: "Hallway Bulb 1"
|
||||||
|
|
||||||
|
esphome:
|
||||||
|
name: ${device_name}
|
||||||
|
comment: ${friendly_name}
|
||||||
|
on_boot:
|
||||||
|
priority: 300
|
||||||
|
then:
|
||||||
|
- light.turn_on:
|
||||||
|
id: my_light
|
||||||
|
- delay: 100ms
|
||||||
|
- light.turn_on:
|
||||||
|
id: my_light
|
||||||
|
brightness: 30%
|
||||||
|
- delay: 100ms
|
||||||
|
- light.turn_on:
|
||||||
|
id: my_light
|
||||||
|
red: 100%
|
||||||
|
green: 50%
|
||||||
|
blue: 0%
|
||||||
|
white: 100%
|
||||||
|
|
||||||
|
esp8266:
|
||||||
|
board: esp01_1m
|
||||||
|
|
||||||
|
interval:
|
||||||
|
- interval: 15s
|
||||||
|
then:
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
api.connected: # check if api connected
|
||||||
|
else:
|
||||||
|
- light.turn_on:
|
||||||
|
id: my_light
|
||||||
|
brightness: 100%
|
||||||
|
|
||||||
|
# Enable Home Assistant API
|
||||||
|
api:
|
||||||
|
batch_delay: 0ms
|
||||||
|
|
||||||
|
ota:
|
||||||
|
platform: esphome
|
||||||
|
|
||||||
|
wifi:
|
||||||
|
ssid: !secret wifi_ssid
|
||||||
|
password: !secret wifi_password
|
||||||
|
fast_connect: True
|
||||||
|
domain: .cloonar.smart
|
||||||
|
|
||||||
|
light:
|
||||||
|
- platform: rgbw
|
||||||
|
id: my_light
|
||||||
|
name: ${friendly_name}
|
||||||
|
red: pwm_r
|
||||||
|
green: pwm_g
|
||||||
|
blue: pwm_b
|
||||||
|
white: pwm_w
|
||||||
|
|
||||||
|
output:
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
pin: GPIO13
|
||||||
|
frequency: 1000 Hz
|
||||||
|
id: pwm_r
|
||||||
|
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
pin: GPIO12
|
||||||
|
frequency: 1000 Hz
|
||||||
|
id: pwm_g
|
||||||
|
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
pin: GPIO14
|
||||||
|
frequency: 1000 Hz
|
||||||
|
id: pwm_b
|
||||||
|
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
pin: GPIO5
|
||||||
|
frequency: 1000 Hz
|
||||||
|
id: pwm_w
|
||||||
80
esphome/hallway-bulb-2.yaml
Normal file
80
esphome/hallway-bulb-2.yaml
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
substitutions:
|
||||||
|
device_name: "hallway-bulb-2"
|
||||||
|
friendly_name: "Hallway Bulb 2"
|
||||||
|
|
||||||
|
esphome:
|
||||||
|
name: ${device_name}
|
||||||
|
comment: ${friendly_name}
|
||||||
|
on_boot:
|
||||||
|
priority: 300
|
||||||
|
then:
|
||||||
|
- light.turn_on:
|
||||||
|
id: my_light
|
||||||
|
- delay: 100ms
|
||||||
|
- light.turn_on:
|
||||||
|
id: my_light
|
||||||
|
brightness: 30%
|
||||||
|
- delay: 100ms
|
||||||
|
- light.turn_on:
|
||||||
|
id: my_light
|
||||||
|
red: 100%
|
||||||
|
green: 50%
|
||||||
|
blue: 0%
|
||||||
|
white: 100%
|
||||||
|
|
||||||
|
esp8266:
|
||||||
|
board: esp01_1m
|
||||||
|
|
||||||
|
interval:
|
||||||
|
- interval: 15s
|
||||||
|
then:
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
api.connected: # check if api connected
|
||||||
|
else:
|
||||||
|
- light.turn_on:
|
||||||
|
id: my_light
|
||||||
|
brightness: 100%
|
||||||
|
|
||||||
|
# Enable Home Assistant API
|
||||||
|
api:
|
||||||
|
batch_delay: 0ms
|
||||||
|
|
||||||
|
ota:
|
||||||
|
platform: esphome
|
||||||
|
|
||||||
|
wifi:
|
||||||
|
ssid: !secret wifi_ssid
|
||||||
|
password: !secret wifi_password
|
||||||
|
fast_connect: True
|
||||||
|
domain: .cloonar.smart
|
||||||
|
|
||||||
|
light:
|
||||||
|
- platform: rgbw
|
||||||
|
id: my_light
|
||||||
|
name: ${friendly_name}
|
||||||
|
red: pwm_r
|
||||||
|
green: pwm_g
|
||||||
|
blue: pwm_b
|
||||||
|
white: pwm_w
|
||||||
|
|
||||||
|
output:
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
pin: GPIO13
|
||||||
|
frequency: 1000 Hz
|
||||||
|
id: pwm_r
|
||||||
|
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
pin: GPIO12
|
||||||
|
frequency: 1000 Hz
|
||||||
|
id: pwm_g
|
||||||
|
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
pin: GPIO14
|
||||||
|
frequency: 1000 Hz
|
||||||
|
id: pwm_b
|
||||||
|
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
pin: GPIO5
|
||||||
|
frequency: 1000 Hz
|
||||||
|
id: pwm_w
|
||||||
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");'
|
||||||
100
esphome/hallway-switch.yaml
Normal file
100
esphome/hallway-switch.yaml
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
substitutions:
|
||||||
|
devicename: hallway-switch
|
||||||
|
max_power: "2000.0" # watt
|
||||||
|
max_temp: "80.0" # °C
|
||||||
|
|
||||||
|
esphome:
|
||||||
|
name: ${devicename}
|
||||||
|
|
||||||
|
#esp32:
|
||||||
|
# board: esp32-c3-devkitm-1
|
||||||
|
# flash_size: 8MB
|
||||||
|
# framework:
|
||||||
|
# type: esp-idf
|
||||||
|
# variant: esp32c3
|
||||||
|
|
||||||
|
esp32:
|
||||||
|
board: esp32-c3-devkitm-1
|
||||||
|
flash_size: 8MB
|
||||||
|
framework:
|
||||||
|
type: esp-idf
|
||||||
|
version: recommended
|
||||||
|
sdkconfig_options:
|
||||||
|
COMPILER_OPTIMIZATION_SIZE: y
|
||||||
|
|
||||||
|
wifi:
|
||||||
|
ssid: !secret wifi_ssid
|
||||||
|
password: !secret wifi_password
|
||||||
|
|
||||||
|
logger:
|
||||||
|
|
||||||
|
api:
|
||||||
|
|
||||||
|
ota:
|
||||||
|
platform: esphome
|
||||||
|
|
||||||
|
sensor:
|
||||||
|
- platform: ntc
|
||||||
|
sensor: temp_resistance_reading
|
||||||
|
name: "Temperature"
|
||||||
|
unit_of_measurement: "°C"
|
||||||
|
accuracy_decimals: 1
|
||||||
|
icon: "mdi:thermometer"
|
||||||
|
calibration:
|
||||||
|
b_constant: 3350
|
||||||
|
reference_resistance: 10kOhm
|
||||||
|
reference_temperature: 298.15K
|
||||||
|
on_value_range:
|
||||||
|
- above: ${max_temp}
|
||||||
|
then:
|
||||||
|
- output.turn_off: relay_output
|
||||||
|
- homeassistant.service:
|
||||||
|
service: persistent_notification.create
|
||||||
|
data:
|
||||||
|
title: Message from ${devicename}
|
||||||
|
data_template:
|
||||||
|
message: Switch turned off because temperature exceeded ${max_temp}°C
|
||||||
|
- platform: resistance
|
||||||
|
id: temp_resistance_reading
|
||||||
|
sensor: temp_analog_reading
|
||||||
|
configuration: DOWNSTREAM
|
||||||
|
resistor: 10kOhm
|
||||||
|
- platform: adc
|
||||||
|
id: temp_analog_reading
|
||||||
|
pin: GPIO3
|
||||||
|
attenuation: 12db
|
||||||
|
|
||||||
|
output:
|
||||||
|
- platform: gpio
|
||||||
|
id: "relay_output"
|
||||||
|
pin: 7
|
||||||
|
|
||||||
|
switch:
|
||||||
|
- platform: output
|
||||||
|
id: "relay"
|
||||||
|
name: "Relay"
|
||||||
|
output: "relay_output"
|
||||||
|
|
||||||
|
binary_sensor:
|
||||||
|
- platform: gpio
|
||||||
|
name: "Switch"
|
||||||
|
pin: 10
|
||||||
|
on_press:
|
||||||
|
then:
|
||||||
|
- switch.toggle: "relay"
|
||||||
|
filters:
|
||||||
|
- delayed_on_off: 50ms
|
||||||
|
|
||||||
|
- platform: gpio
|
||||||
|
name: "Button"
|
||||||
|
pin:
|
||||||
|
number: 1
|
||||||
|
inverted: yes
|
||||||
|
mode:
|
||||||
|
input: true
|
||||||
|
pullup: true
|
||||||
|
|
||||||
|
status_led:
|
||||||
|
pin:
|
||||||
|
number: 0
|
||||||
|
inverted: true
|
||||||
214
esphome/livingroom-bulb-1.yaml
Normal file
214
esphome/livingroom-bulb-1.yaml
Normal file
@@ -0,0 +1,214 @@
|
|||||||
|
substitutions:
|
||||||
|
name: "livingroom-bulb-1"
|
||||||
|
friendly_name: "Living Room Bulb 1"
|
||||||
|
room: "Living Room"
|
||||||
|
device_description: "athom 7w rgbcw light bulb"
|
||||||
|
project_name: "Athom Technology.Athom RGBCW Bulb"
|
||||||
|
dns_domain: ".cloonar.smart"
|
||||||
|
timezone: ""
|
||||||
|
sntp_update_interval: 6h
|
||||||
|
sntp_server_1: "0.pool.ntp.org"
|
||||||
|
sntp_server_2: "1.pool.ntp.org"
|
||||||
|
sntp_server_3: "2.pool.ntp.org"
|
||||||
|
|
||||||
|
esphome:
|
||||||
|
name: "${name}"
|
||||||
|
friendly_name: "${friendly_name}"
|
||||||
|
comment: "${device_description}"
|
||||||
|
area: "${room}"
|
||||||
|
name_add_mac_suffix: false
|
||||||
|
min_version: 2024.6.0
|
||||||
|
project:
|
||||||
|
name: "${project_name}"
|
||||||
|
version: "${project_version}"
|
||||||
|
on_boot:
|
||||||
|
then:
|
||||||
|
- light.turn_on:
|
||||||
|
id: rgbww_light
|
||||||
|
- delay: 100ms
|
||||||
|
- light.turn_on:
|
||||||
|
id: rgbww_light
|
||||||
|
brightness: 20%
|
||||||
|
- delay: 100ms
|
||||||
|
- light.turn_on:
|
||||||
|
id: rgbww_light
|
||||||
|
red: 100%
|
||||||
|
green: 50%
|
||||||
|
blue: 0%
|
||||||
|
white: 100%
|
||||||
|
|
||||||
|
interval:
|
||||||
|
- interval: 15s
|
||||||
|
then:
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
api.connected:
|
||||||
|
else:
|
||||||
|
- light.turn_on:
|
||||||
|
id: rgbww_light
|
||||||
|
brightness: 100%
|
||||||
|
|
||||||
|
esp8266:
|
||||||
|
board: esp8285
|
||||||
|
restore_from_flash: true
|
||||||
|
|
||||||
|
preferences:
|
||||||
|
flash_write_interval: 1min
|
||||||
|
|
||||||
|
api:
|
||||||
|
batch_delay: 0ms
|
||||||
|
|
||||||
|
ota:
|
||||||
|
- platform: esphome
|
||||||
|
|
||||||
|
wifi:
|
||||||
|
# Disable fast_connect so we do a full scan (required for hidden SSIDs)
|
||||||
|
fast_connect: True
|
||||||
|
domain: "${dns_domain}"
|
||||||
|
|
||||||
|
# Your hidden network
|
||||||
|
networks:
|
||||||
|
- ssid: !secret wifi_ssid
|
||||||
|
password: !secret wifi_password
|
||||||
|
channel: 1
|
||||||
|
hidden: true
|
||||||
|
|
||||||
|
manual_ip:
|
||||||
|
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
|
||||||
|
|
||||||
|
binary_sensor:
|
||||||
|
- platform: status
|
||||||
|
name: "Status"
|
||||||
|
entity_category: diagnostic
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
output:
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
id: red_output
|
||||||
|
pin: GPIO4
|
||||||
|
min_power: 0.000499
|
||||||
|
max_power: 1
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
id: green_output
|
||||||
|
pin: GPIO12
|
||||||
|
min_power: 0.000499
|
||||||
|
max_power: 1
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
id: blue_output
|
||||||
|
pin: GPIO14
|
||||||
|
min_power: 0.000499
|
||||||
|
max_power: 1
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
id: warm_white_output
|
||||||
|
pin: GPIO13
|
||||||
|
min_power: 0.000499
|
||||||
|
max_power: 0.9
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
id: white_output
|
||||||
|
pin: GPIO5
|
||||||
|
min_power: 0.000499
|
||||||
|
max_power: 0.9
|
||||||
|
|
||||||
|
light:
|
||||||
|
- platform: rgbww
|
||||||
|
id: rgbww_light
|
||||||
|
name: "RGBCW_Bulb"
|
||||||
|
red: red_output
|
||||||
|
green: green_output
|
||||||
|
blue: blue_output
|
||||||
|
warm_white: warm_white_output
|
||||||
|
cold_white: white_output
|
||||||
|
cold_white_color_temperature: 6000 K
|
||||||
|
warm_white_color_temperature: 3000 K
|
||||||
|
color_interlock: true
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
- platform: template
|
||||||
|
name: 'Last Restart'
|
||||||
|
id: device_last_restart
|
||||||
|
icon: mdi:clock
|
||||||
|
entity_category: diagnostic
|
||||||
|
|
||||||
|
- platform: template
|
||||||
|
name: "Uptime"
|
||||||
|
entity_category: diagnostic
|
||||||
|
lambda: |-
|
||||||
|
int seconds = (id(uptime_sensor).state);
|
||||||
|
int days = seconds / (24 * 3600);
|
||||||
|
seconds %= (24 * 3600);
|
||||||
|
int hours = seconds / 3600;
|
||||||
|
seconds %= 3600;
|
||||||
|
int minutes = seconds / 60;
|
||||||
|
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
|
||||||
|
timezone: "${timezone}"
|
||||||
|
update_interval: ${sntp_update_interval}
|
||||||
|
servers:
|
||||||
|
- "${sntp_server_1}"
|
||||||
|
- "${sntp_server_2}"
|
||||||
|
- "${sntp_server_3}"
|
||||||
|
on_time_sync:
|
||||||
|
then:
|
||||||
|
- 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");'
|
||||||
214
esphome/livingroom-bulb-2.yaml
Normal file
214
esphome/livingroom-bulb-2.yaml
Normal file
@@ -0,0 +1,214 @@
|
|||||||
|
substitutions:
|
||||||
|
name: "livingroom-bulb-2"
|
||||||
|
friendly_name: "Living Room Bulb 2"
|
||||||
|
room: "Living Room"
|
||||||
|
device_description: "athom 7w rgbcw light bulb"
|
||||||
|
project_name: "Athom Technology.Athom RGBCW Bulb"
|
||||||
|
dns_domain: ".cloonar.smart"
|
||||||
|
timezone: ""
|
||||||
|
sntp_update_interval: 6h
|
||||||
|
sntp_server_1: "0.pool.ntp.org"
|
||||||
|
sntp_server_2: "1.pool.ntp.org"
|
||||||
|
sntp_server_3: "2.pool.ntp.org"
|
||||||
|
|
||||||
|
esphome:
|
||||||
|
name: "${name}"
|
||||||
|
friendly_name: "${friendly_name}"
|
||||||
|
comment: "${device_description}"
|
||||||
|
area: "${room}"
|
||||||
|
name_add_mac_suffix: false
|
||||||
|
min_version: 2024.6.0
|
||||||
|
project:
|
||||||
|
name: "${project_name}"
|
||||||
|
version: "${project_version}"
|
||||||
|
on_boot:
|
||||||
|
then:
|
||||||
|
- light.turn_on:
|
||||||
|
id: rgbww_light
|
||||||
|
- delay: 100ms
|
||||||
|
- light.turn_on:
|
||||||
|
id: rgbww_light
|
||||||
|
brightness: 20%
|
||||||
|
- delay: 100ms
|
||||||
|
- light.turn_on:
|
||||||
|
id: rgbww_light
|
||||||
|
red: 100%
|
||||||
|
green: 50%
|
||||||
|
blue: 0%
|
||||||
|
white: 100%
|
||||||
|
|
||||||
|
interval:
|
||||||
|
- interval: 15s
|
||||||
|
then:
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
api.connected:
|
||||||
|
else:
|
||||||
|
- light.turn_on:
|
||||||
|
id: rgbww_light
|
||||||
|
brightness: 100%
|
||||||
|
|
||||||
|
esp8266:
|
||||||
|
board: esp8285
|
||||||
|
restore_from_flash: true
|
||||||
|
|
||||||
|
preferences:
|
||||||
|
flash_write_interval: 1min
|
||||||
|
|
||||||
|
api:
|
||||||
|
batch_delay: 0ms
|
||||||
|
|
||||||
|
ota:
|
||||||
|
- platform: esphome
|
||||||
|
|
||||||
|
wifi:
|
||||||
|
# Disable fast_connect so we do a full scan (required for hidden SSIDs)
|
||||||
|
fast_connect: True
|
||||||
|
domain: "${dns_domain}"
|
||||||
|
|
||||||
|
# Your hidden network
|
||||||
|
networks:
|
||||||
|
- ssid: !secret wifi_ssid
|
||||||
|
password: !secret wifi_password
|
||||||
|
channel: 1
|
||||||
|
hidden: true
|
||||||
|
|
||||||
|
manual_ip:
|
||||||
|
static_ip: 10.42.100.12
|
||||||
|
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
|
||||||
|
|
||||||
|
binary_sensor:
|
||||||
|
- platform: status
|
||||||
|
name: "Status"
|
||||||
|
entity_category: diagnostic
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
output:
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
id: red_output
|
||||||
|
pin: GPIO4
|
||||||
|
min_power: 0.000499
|
||||||
|
max_power: 1
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
id: green_output
|
||||||
|
pin: GPIO12
|
||||||
|
min_power: 0.000499
|
||||||
|
max_power: 1
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
id: blue_output
|
||||||
|
pin: GPIO14
|
||||||
|
min_power: 0.000499
|
||||||
|
max_power: 1
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
id: warm_white_output
|
||||||
|
pin: GPIO13
|
||||||
|
min_power: 0.000499
|
||||||
|
max_power: 0.9
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
id: white_output
|
||||||
|
pin: GPIO5
|
||||||
|
min_power: 0.000499
|
||||||
|
max_power: 0.9
|
||||||
|
|
||||||
|
light:
|
||||||
|
- platform: rgbww
|
||||||
|
id: rgbww_light
|
||||||
|
name: "RGBCW_Bulb"
|
||||||
|
red: red_output
|
||||||
|
green: green_output
|
||||||
|
blue: blue_output
|
||||||
|
warm_white: warm_white_output
|
||||||
|
cold_white: white_output
|
||||||
|
cold_white_color_temperature: 6000 K
|
||||||
|
warm_white_color_temperature: 3000 K
|
||||||
|
color_interlock: true
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
- platform: template
|
||||||
|
name: 'Last Restart'
|
||||||
|
id: device_last_restart
|
||||||
|
icon: mdi:clock
|
||||||
|
entity_category: diagnostic
|
||||||
|
|
||||||
|
- platform: template
|
||||||
|
name: "Uptime"
|
||||||
|
entity_category: diagnostic
|
||||||
|
lambda: |-
|
||||||
|
int seconds = (id(uptime_sensor).state);
|
||||||
|
int days = seconds / (24 * 3600);
|
||||||
|
seconds %= (24 * 3600);
|
||||||
|
int hours = seconds / 3600;
|
||||||
|
seconds %= 3600;
|
||||||
|
int minutes = seconds / 60;
|
||||||
|
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
|
||||||
|
timezone: "${timezone}"
|
||||||
|
update_interval: ${sntp_update_interval}
|
||||||
|
servers:
|
||||||
|
- "${sntp_server_1}"
|
||||||
|
- "${sntp_server_2}"
|
||||||
|
- "${sntp_server_3}"
|
||||||
|
on_time_sync:
|
||||||
|
then:
|
||||||
|
- 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");'
|
||||||
214
esphome/livingroom-bulb-3.yaml
Normal file
214
esphome/livingroom-bulb-3.yaml
Normal file
@@ -0,0 +1,214 @@
|
|||||||
|
substitutions:
|
||||||
|
name: "livingroom-bulb-3"
|
||||||
|
friendly_name: "Living Room Bulb 3"
|
||||||
|
room: "Living Room"
|
||||||
|
device_description: "athom 7w rgbcw light bulb"
|
||||||
|
project_name: "Athom Technology.Athom RGBCW Bulb"
|
||||||
|
dns_domain: ".cloonar.smart"
|
||||||
|
timezone: ""
|
||||||
|
sntp_update_interval: 6h
|
||||||
|
sntp_server_1: "0.pool.ntp.org"
|
||||||
|
sntp_server_2: "1.pool.ntp.org"
|
||||||
|
sntp_server_3: "2.pool.ntp.org"
|
||||||
|
|
||||||
|
esphome:
|
||||||
|
name: "${name}"
|
||||||
|
friendly_name: "${friendly_name}"
|
||||||
|
comment: "${device_description}"
|
||||||
|
area: "${room}"
|
||||||
|
name_add_mac_suffix: false
|
||||||
|
min_version: 2024.6.0
|
||||||
|
project:
|
||||||
|
name: "${project_name}"
|
||||||
|
version: "${project_version}"
|
||||||
|
on_boot:
|
||||||
|
then:
|
||||||
|
- light.turn_on:
|
||||||
|
id: rgbww_light
|
||||||
|
- delay: 100ms
|
||||||
|
- light.turn_on:
|
||||||
|
id: rgbww_light
|
||||||
|
brightness: 20%
|
||||||
|
- delay: 100ms
|
||||||
|
- light.turn_on:
|
||||||
|
id: rgbww_light
|
||||||
|
red: 100%
|
||||||
|
green: 50%
|
||||||
|
blue: 0%
|
||||||
|
white: 100%
|
||||||
|
|
||||||
|
interval:
|
||||||
|
- interval: 15s
|
||||||
|
then:
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
api.connected:
|
||||||
|
else:
|
||||||
|
- light.turn_on:
|
||||||
|
id: rgbww_light
|
||||||
|
brightness: 100%
|
||||||
|
|
||||||
|
esp8266:
|
||||||
|
board: esp8285
|
||||||
|
restore_from_flash: true
|
||||||
|
|
||||||
|
preferences:
|
||||||
|
flash_write_interval: 1min
|
||||||
|
|
||||||
|
api:
|
||||||
|
batch_delay: 0ms
|
||||||
|
|
||||||
|
ota:
|
||||||
|
- platform: esphome
|
||||||
|
|
||||||
|
wifi:
|
||||||
|
# Disable fast_connect so we do a full scan (required for hidden SSIDs)
|
||||||
|
fast_connect: True
|
||||||
|
domain: "${dns_domain}"
|
||||||
|
|
||||||
|
# Your hidden network
|
||||||
|
networks:
|
||||||
|
- ssid: !secret wifi_ssid
|
||||||
|
password: !secret wifi_password
|
||||||
|
channel: 1
|
||||||
|
hidden: true
|
||||||
|
|
||||||
|
manual_ip:
|
||||||
|
static_ip: 10.42.100.13
|
||||||
|
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
|
||||||
|
|
||||||
|
binary_sensor:
|
||||||
|
- platform: status
|
||||||
|
name: "Status"
|
||||||
|
entity_category: diagnostic
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
output:
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
id: red_output
|
||||||
|
pin: GPIO4
|
||||||
|
min_power: 0.000499
|
||||||
|
max_power: 1
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
id: green_output
|
||||||
|
pin: GPIO12
|
||||||
|
min_power: 0.000499
|
||||||
|
max_power: 1
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
id: blue_output
|
||||||
|
pin: GPIO14
|
||||||
|
min_power: 0.000499
|
||||||
|
max_power: 1
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
id: warm_white_output
|
||||||
|
pin: GPIO13
|
||||||
|
min_power: 0.000499
|
||||||
|
max_power: 0.9
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
id: white_output
|
||||||
|
pin: GPIO5
|
||||||
|
min_power: 0.000499
|
||||||
|
max_power: 0.9
|
||||||
|
|
||||||
|
light:
|
||||||
|
- platform: rgbww
|
||||||
|
id: rgbww_light
|
||||||
|
name: "RGBCW_Bulb"
|
||||||
|
red: red_output
|
||||||
|
green: green_output
|
||||||
|
blue: blue_output
|
||||||
|
warm_white: warm_white_output
|
||||||
|
cold_white: white_output
|
||||||
|
cold_white_color_temperature: 6000 K
|
||||||
|
warm_white_color_temperature: 3000 K
|
||||||
|
color_interlock: true
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
- platform: template
|
||||||
|
name: 'Last Restart'
|
||||||
|
id: device_last_restart
|
||||||
|
icon: mdi:clock
|
||||||
|
entity_category: diagnostic
|
||||||
|
|
||||||
|
- platform: template
|
||||||
|
name: "Uptime"
|
||||||
|
entity_category: diagnostic
|
||||||
|
lambda: |-
|
||||||
|
int seconds = (id(uptime_sensor).state);
|
||||||
|
int days = seconds / (24 * 3600);
|
||||||
|
seconds %= (24 * 3600);
|
||||||
|
int hours = seconds / 3600;
|
||||||
|
seconds %= 3600;
|
||||||
|
int minutes = seconds / 60;
|
||||||
|
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
|
||||||
|
timezone: "${timezone}"
|
||||||
|
update_interval: ${sntp_update_interval}
|
||||||
|
servers:
|
||||||
|
- "${sntp_server_1}"
|
||||||
|
- "${sntp_server_2}"
|
||||||
|
- "${sntp_server_3}"
|
||||||
|
on_time_sync:
|
||||||
|
then:
|
||||||
|
- 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");'
|
||||||
214
esphome/livingroom-bulb-4.yaml
Normal file
214
esphome/livingroom-bulb-4.yaml
Normal file
@@ -0,0 +1,214 @@
|
|||||||
|
substitutions:
|
||||||
|
name: "livingroom-bulb-4"
|
||||||
|
friendly_name: "Living Room Bulb 4"
|
||||||
|
room: "Living Room"
|
||||||
|
device_description: "athom 7w rgbcw light bulb"
|
||||||
|
project_name: "Athom Technology.Athom RGBCW Bulb"
|
||||||
|
dns_domain: ".cloonar.smart"
|
||||||
|
timezone: ""
|
||||||
|
sntp_update_interval: 6h
|
||||||
|
sntp_server_1: "0.pool.ntp.org"
|
||||||
|
sntp_server_2: "1.pool.ntp.org"
|
||||||
|
sntp_server_3: "2.pool.ntp.org"
|
||||||
|
|
||||||
|
esphome:
|
||||||
|
name: "${name}"
|
||||||
|
friendly_name: "${friendly_name}"
|
||||||
|
comment: "${device_description}"
|
||||||
|
area: "${room}"
|
||||||
|
name_add_mac_suffix: false
|
||||||
|
min_version: 2024.6.0
|
||||||
|
project:
|
||||||
|
name: "${project_name}"
|
||||||
|
version: "${project_version}"
|
||||||
|
on_boot:
|
||||||
|
then:
|
||||||
|
- light.turn_on:
|
||||||
|
id: rgbww_light
|
||||||
|
- delay: 100ms
|
||||||
|
- light.turn_on:
|
||||||
|
id: rgbww_light
|
||||||
|
brightness: 20%
|
||||||
|
- delay: 100ms
|
||||||
|
- light.turn_on:
|
||||||
|
id: rgbww_light
|
||||||
|
red: 100%
|
||||||
|
green: 50%
|
||||||
|
blue: 0%
|
||||||
|
white: 100%
|
||||||
|
|
||||||
|
interval:
|
||||||
|
- interval: 15s
|
||||||
|
then:
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
api.connected:
|
||||||
|
else:
|
||||||
|
- light.turn_on:
|
||||||
|
id: rgbww_light
|
||||||
|
brightness: 100%
|
||||||
|
|
||||||
|
esp8266:
|
||||||
|
board: esp8285
|
||||||
|
restore_from_flash: true
|
||||||
|
|
||||||
|
preferences:
|
||||||
|
flash_write_interval: 1min
|
||||||
|
|
||||||
|
api:
|
||||||
|
batch_delay: 0ms
|
||||||
|
|
||||||
|
ota:
|
||||||
|
- platform: esphome
|
||||||
|
|
||||||
|
wifi:
|
||||||
|
# Disable fast_connect so we do a full scan (required for hidden SSIDs)
|
||||||
|
fast_connect: True
|
||||||
|
domain: "${dns_domain}"
|
||||||
|
|
||||||
|
# Your hidden network
|
||||||
|
networks:
|
||||||
|
- ssid: !secret wifi_ssid
|
||||||
|
password: !secret wifi_password
|
||||||
|
channel: 1
|
||||||
|
hidden: true
|
||||||
|
|
||||||
|
manual_ip:
|
||||||
|
static_ip: 10.42.100.14
|
||||||
|
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
|
||||||
|
|
||||||
|
binary_sensor:
|
||||||
|
- platform: status
|
||||||
|
name: "Status"
|
||||||
|
entity_category: diagnostic
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
output:
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
id: red_output
|
||||||
|
pin: GPIO4
|
||||||
|
min_power: 0.000499
|
||||||
|
max_power: 1
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
id: green_output
|
||||||
|
pin: GPIO12
|
||||||
|
min_power: 0.000499
|
||||||
|
max_power: 1
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
id: blue_output
|
||||||
|
pin: GPIO14
|
||||||
|
min_power: 0.000499
|
||||||
|
max_power: 1
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
id: warm_white_output
|
||||||
|
pin: GPIO13
|
||||||
|
min_power: 0.000499
|
||||||
|
max_power: 0.9
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
id: white_output
|
||||||
|
pin: GPIO5
|
||||||
|
min_power: 0.000499
|
||||||
|
max_power: 0.9
|
||||||
|
|
||||||
|
light:
|
||||||
|
- platform: rgbww
|
||||||
|
id: rgbww_light
|
||||||
|
name: "RGBCW_Bulb"
|
||||||
|
red: red_output
|
||||||
|
green: green_output
|
||||||
|
blue: blue_output
|
||||||
|
warm_white: warm_white_output
|
||||||
|
cold_white: white_output
|
||||||
|
cold_white_color_temperature: 6000 K
|
||||||
|
warm_white_color_temperature: 3000 K
|
||||||
|
color_interlock: true
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
- platform: template
|
||||||
|
name: 'Last Restart'
|
||||||
|
id: device_last_restart
|
||||||
|
icon: mdi:clock
|
||||||
|
entity_category: diagnostic
|
||||||
|
|
||||||
|
- platform: template
|
||||||
|
name: "Uptime"
|
||||||
|
entity_category: diagnostic
|
||||||
|
lambda: |-
|
||||||
|
int seconds = (id(uptime_sensor).state);
|
||||||
|
int days = seconds / (24 * 3600);
|
||||||
|
seconds %= (24 * 3600);
|
||||||
|
int hours = seconds / 3600;
|
||||||
|
seconds %= 3600;
|
||||||
|
int minutes = seconds / 60;
|
||||||
|
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
|
||||||
|
timezone: "${timezone}"
|
||||||
|
update_interval: ${sntp_update_interval}
|
||||||
|
servers:
|
||||||
|
- "${sntp_server_1}"
|
||||||
|
- "${sntp_server_2}"
|
||||||
|
- "${sntp_server_3}"
|
||||||
|
on_time_sync:
|
||||||
|
then:
|
||||||
|
- 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");'
|
||||||
214
esphome/livingroom-bulb-5.yaml
Normal file
214
esphome/livingroom-bulb-5.yaml
Normal file
@@ -0,0 +1,214 @@
|
|||||||
|
substitutions:
|
||||||
|
name: "livingroom-bulb-5"
|
||||||
|
friendly_name: "Living Room Bulb 5"
|
||||||
|
room: "Living Room"
|
||||||
|
device_description: "athom 7w rgbcw light bulb"
|
||||||
|
project_name: "Athom Technology.Athom RGBCW Bulb"
|
||||||
|
dns_domain: ".cloonar.smart"
|
||||||
|
timezone: ""
|
||||||
|
sntp_update_interval: 6h
|
||||||
|
sntp_server_1: "0.pool.ntp.org"
|
||||||
|
sntp_server_2: "1.pool.ntp.org"
|
||||||
|
sntp_server_3: "2.pool.ntp.org"
|
||||||
|
|
||||||
|
esphome:
|
||||||
|
name: "${name}"
|
||||||
|
friendly_name: "${friendly_name}"
|
||||||
|
comment: "${device_description}"
|
||||||
|
area: "${room}"
|
||||||
|
name_add_mac_suffix: false
|
||||||
|
min_version: 2024.6.0
|
||||||
|
project:
|
||||||
|
name: "${project_name}"
|
||||||
|
version: "${project_version}"
|
||||||
|
on_boot:
|
||||||
|
then:
|
||||||
|
- light.turn_on:
|
||||||
|
id: rgbww_light
|
||||||
|
- delay: 100ms
|
||||||
|
- light.turn_on:
|
||||||
|
id: rgbww_light
|
||||||
|
brightness: 20%
|
||||||
|
- delay: 100ms
|
||||||
|
- light.turn_on:
|
||||||
|
id: rgbww_light
|
||||||
|
red: 100%
|
||||||
|
green: 50%
|
||||||
|
blue: 0%
|
||||||
|
white: 100%
|
||||||
|
|
||||||
|
interval:
|
||||||
|
- interval: 15s
|
||||||
|
then:
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
api.connected:
|
||||||
|
else:
|
||||||
|
- light.turn_on:
|
||||||
|
id: rgbww_light
|
||||||
|
brightness: 100%
|
||||||
|
|
||||||
|
esp8266:
|
||||||
|
board: esp8285
|
||||||
|
restore_from_flash: true
|
||||||
|
|
||||||
|
preferences:
|
||||||
|
flash_write_interval: 1min
|
||||||
|
|
||||||
|
api:
|
||||||
|
batch_delay: 0ms
|
||||||
|
|
||||||
|
ota:
|
||||||
|
- platform: esphome
|
||||||
|
|
||||||
|
wifi:
|
||||||
|
# Disable fast_connect so we do a full scan (required for hidden SSIDs)
|
||||||
|
fast_connect: True
|
||||||
|
domain: "${dns_domain}"
|
||||||
|
|
||||||
|
# Your hidden network
|
||||||
|
networks:
|
||||||
|
- ssid: !secret wifi_ssid
|
||||||
|
password: !secret wifi_password
|
||||||
|
channel: 1
|
||||||
|
hidden: true
|
||||||
|
|
||||||
|
manual_ip:
|
||||||
|
static_ip: 10.42.100.15
|
||||||
|
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
|
||||||
|
|
||||||
|
binary_sensor:
|
||||||
|
- platform: status
|
||||||
|
name: "Status"
|
||||||
|
entity_category: diagnostic
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
output:
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
id: red_output
|
||||||
|
pin: GPIO4
|
||||||
|
min_power: 0.000499
|
||||||
|
max_power: 1
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
id: green_output
|
||||||
|
pin: GPIO12
|
||||||
|
min_power: 0.000499
|
||||||
|
max_power: 1
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
id: blue_output
|
||||||
|
pin: GPIO14
|
||||||
|
min_power: 0.000499
|
||||||
|
max_power: 1
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
id: warm_white_output
|
||||||
|
pin: GPIO13
|
||||||
|
min_power: 0.000499
|
||||||
|
max_power: 0.9
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
id: white_output
|
||||||
|
pin: GPIO5
|
||||||
|
min_power: 0.000499
|
||||||
|
max_power: 0.9
|
||||||
|
|
||||||
|
light:
|
||||||
|
- platform: rgbww
|
||||||
|
id: rgbww_light
|
||||||
|
name: "RGBCW_Bulb"
|
||||||
|
red: red_output
|
||||||
|
green: green_output
|
||||||
|
blue: blue_output
|
||||||
|
warm_white: warm_white_output
|
||||||
|
cold_white: white_output
|
||||||
|
cold_white_color_temperature: 6000 K
|
||||||
|
warm_white_color_temperature: 3000 K
|
||||||
|
color_interlock: true
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
- platform: template
|
||||||
|
name: 'Last Restart'
|
||||||
|
id: device_last_restart
|
||||||
|
icon: mdi:clock
|
||||||
|
entity_category: diagnostic
|
||||||
|
|
||||||
|
- platform: template
|
||||||
|
name: "Uptime"
|
||||||
|
entity_category: diagnostic
|
||||||
|
lambda: |-
|
||||||
|
int seconds = (id(uptime_sensor).state);
|
||||||
|
int days = seconds / (24 * 3600);
|
||||||
|
seconds %= (24 * 3600);
|
||||||
|
int hours = seconds / 3600;
|
||||||
|
seconds %= 3600;
|
||||||
|
int minutes = seconds / 60;
|
||||||
|
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
|
||||||
|
timezone: "${timezone}"
|
||||||
|
update_interval: ${sntp_update_interval}
|
||||||
|
servers:
|
||||||
|
- "${sntp_server_1}"
|
||||||
|
- "${sntp_server_2}"
|
||||||
|
- "${sntp_server_3}"
|
||||||
|
on_time_sync:
|
||||||
|
then:
|
||||||
|
- 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");'
|
||||||
214
esphome/livingroom-bulb-6.yaml
Normal file
214
esphome/livingroom-bulb-6.yaml
Normal file
@@ -0,0 +1,214 @@
|
|||||||
|
substitutions:
|
||||||
|
name: "livingroom-bulb-6"
|
||||||
|
friendly_name: "Living Room Bulb 6"
|
||||||
|
room: "Living Room"
|
||||||
|
device_description: "athom 7w rgbcw light bulb"
|
||||||
|
project_name: "Athom Technology.Athom RGBCW Bulb"
|
||||||
|
dns_domain: ".cloonar.smart"
|
||||||
|
timezone: ""
|
||||||
|
sntp_update_interval: 6h
|
||||||
|
sntp_server_1: "0.pool.ntp.org"
|
||||||
|
sntp_server_2: "1.pool.ntp.org"
|
||||||
|
sntp_server_3: "2.pool.ntp.org"
|
||||||
|
|
||||||
|
esphome:
|
||||||
|
name: "${name}"
|
||||||
|
friendly_name: "${friendly_name}"
|
||||||
|
comment: "${device_description}"
|
||||||
|
area: "${room}"
|
||||||
|
name_add_mac_suffix: false
|
||||||
|
min_version: 2024.6.0
|
||||||
|
project:
|
||||||
|
name: "${project_name}"
|
||||||
|
version: "${project_version}"
|
||||||
|
on_boot:
|
||||||
|
then:
|
||||||
|
- light.turn_on:
|
||||||
|
id: rgbww_light
|
||||||
|
- delay: 100ms
|
||||||
|
- light.turn_on:
|
||||||
|
id: rgbww_light
|
||||||
|
brightness: 20%
|
||||||
|
- delay: 100ms
|
||||||
|
- light.turn_on:
|
||||||
|
id: rgbww_light
|
||||||
|
red: 100%
|
||||||
|
green: 50%
|
||||||
|
blue: 0%
|
||||||
|
white: 100%
|
||||||
|
|
||||||
|
interval:
|
||||||
|
- interval: 15s
|
||||||
|
then:
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
api.connected:
|
||||||
|
else:
|
||||||
|
- light.turn_on:
|
||||||
|
id: rgbww_light
|
||||||
|
brightness: 100%
|
||||||
|
|
||||||
|
esp8266:
|
||||||
|
board: esp8285
|
||||||
|
restore_from_flash: true
|
||||||
|
|
||||||
|
preferences:
|
||||||
|
flash_write_interval: 1min
|
||||||
|
|
||||||
|
api:
|
||||||
|
batch_delay: 0ms
|
||||||
|
|
||||||
|
ota:
|
||||||
|
- platform: esphome
|
||||||
|
|
||||||
|
wifi:
|
||||||
|
# Disable fast_connect so we do a full scan (required for hidden SSIDs)
|
||||||
|
fast_connect: True
|
||||||
|
domain: "${dns_domain}"
|
||||||
|
|
||||||
|
# Your hidden network
|
||||||
|
networks:
|
||||||
|
- ssid: !secret wifi_ssid
|
||||||
|
password: !secret wifi_password
|
||||||
|
channel: 1
|
||||||
|
hidden: true
|
||||||
|
|
||||||
|
manual_ip:
|
||||||
|
static_ip: 10.42.100.16
|
||||||
|
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
|
||||||
|
|
||||||
|
binary_sensor:
|
||||||
|
- platform: status
|
||||||
|
name: "Status"
|
||||||
|
entity_category: diagnostic
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
output:
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
id: red_output
|
||||||
|
pin: GPIO4
|
||||||
|
min_power: 0.000499
|
||||||
|
max_power: 1
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
id: green_output
|
||||||
|
pin: GPIO12
|
||||||
|
min_power: 0.000499
|
||||||
|
max_power: 1
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
id: blue_output
|
||||||
|
pin: GPIO14
|
||||||
|
min_power: 0.000499
|
||||||
|
max_power: 1
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
id: warm_white_output
|
||||||
|
pin: GPIO13
|
||||||
|
min_power: 0.000499
|
||||||
|
max_power: 0.9
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
id: white_output
|
||||||
|
pin: GPIO5
|
||||||
|
min_power: 0.000499
|
||||||
|
max_power: 0.9
|
||||||
|
|
||||||
|
light:
|
||||||
|
- platform: rgbww
|
||||||
|
id: rgbww_light
|
||||||
|
name: "RGBCW_Bulb"
|
||||||
|
red: red_output
|
||||||
|
green: green_output
|
||||||
|
blue: blue_output
|
||||||
|
warm_white: warm_white_output
|
||||||
|
cold_white: white_output
|
||||||
|
cold_white_color_temperature: 6000 K
|
||||||
|
warm_white_color_temperature: 3000 K
|
||||||
|
color_interlock: true
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
- platform: template
|
||||||
|
name: 'Last Restart'
|
||||||
|
id: device_last_restart
|
||||||
|
icon: mdi:clock
|
||||||
|
entity_category: diagnostic
|
||||||
|
|
||||||
|
- platform: template
|
||||||
|
name: "Uptime"
|
||||||
|
entity_category: diagnostic
|
||||||
|
lambda: |-
|
||||||
|
int seconds = (id(uptime_sensor).state);
|
||||||
|
int days = seconds / (24 * 3600);
|
||||||
|
seconds %= (24 * 3600);
|
||||||
|
int hours = seconds / 3600;
|
||||||
|
seconds %= 3600;
|
||||||
|
int minutes = seconds / 60;
|
||||||
|
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
|
||||||
|
timezone: "${timezone}"
|
||||||
|
update_interval: ${sntp_update_interval}
|
||||||
|
servers:
|
||||||
|
- "${sntp_server_1}"
|
||||||
|
- "${sntp_server_2}"
|
||||||
|
- "${sntp_server_3}"
|
||||||
|
on_time_sync:
|
||||||
|
then:
|
||||||
|
- 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");'
|
||||||
33
esphome/presense-bedroom.yaml
Normal file
33
esphome/presense-bedroom.yaml
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
esphome:
|
||||||
|
name: presense-bedroom
|
||||||
|
friendly_name: presense-bedroom
|
||||||
|
|
||||||
|
esp32:
|
||||||
|
board: esp32dev
|
||||||
|
framework:
|
||||||
|
type: arduino
|
||||||
|
|
||||||
|
# Enable logging
|
||||||
|
logger:
|
||||||
|
|
||||||
|
# Enable Home Assistant API
|
||||||
|
api:
|
||||||
|
|
||||||
|
ota:
|
||||||
|
- platform: esphome
|
||||||
|
|
||||||
|
wifi:
|
||||||
|
ssid: !secret wifi_ssid
|
||||||
|
password: !secret wifi_password
|
||||||
|
fast_connect: True
|
||||||
|
domain: .cloonar.smart
|
||||||
|
|
||||||
|
# Enable fallback hotspot (captive portal) in case wifi connection fails
|
||||||
|
ap:
|
||||||
|
ssid: "Presense-Bedroom Fallback"
|
||||||
|
password: "jMTo5YkCC01q"
|
||||||
|
|
||||||
|
captive_portal:
|
||||||
|
|
||||||
|
bluetooth_proxy:
|
||||||
|
|
||||||
33
esphome/presense-hallway.yaml
Normal file
33
esphome/presense-hallway.yaml
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
esphome:
|
||||||
|
name: presense-hallway
|
||||||
|
friendly_name: presense-hallway
|
||||||
|
|
||||||
|
esp32:
|
||||||
|
board: esp32dev
|
||||||
|
framework:
|
||||||
|
type: arduino
|
||||||
|
|
||||||
|
# Enable logging
|
||||||
|
logger:
|
||||||
|
|
||||||
|
# Enable Home Assistant API
|
||||||
|
api:
|
||||||
|
|
||||||
|
ota:
|
||||||
|
- platform: esphome
|
||||||
|
|
||||||
|
wifi:
|
||||||
|
ssid: !secret wifi_ssid
|
||||||
|
password: !secret wifi_password
|
||||||
|
fast_connect: True
|
||||||
|
domain: .cloonar.smart
|
||||||
|
|
||||||
|
# Enable fallback hotspot (captive portal) in case wifi connection fails
|
||||||
|
ap:
|
||||||
|
ssid: "Presense-Hallway Fallback"
|
||||||
|
password: "jMTo5YkCC01q"
|
||||||
|
|
||||||
|
captive_portal:
|
||||||
|
|
||||||
|
bluetooth_proxy:
|
||||||
|
|
||||||
33
esphome/presense-kitchen.yaml
Normal file
33
esphome/presense-kitchen.yaml
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
esphome:
|
||||||
|
name: presense-kitchen
|
||||||
|
friendly_name: presense-kitchen
|
||||||
|
|
||||||
|
esp32:
|
||||||
|
board: esp32dev
|
||||||
|
framework:
|
||||||
|
type: arduino
|
||||||
|
|
||||||
|
# Enable logging
|
||||||
|
logger:
|
||||||
|
|
||||||
|
# Enable Home Assistant API
|
||||||
|
api:
|
||||||
|
|
||||||
|
ota:
|
||||||
|
- platform: esphome
|
||||||
|
|
||||||
|
wifi:
|
||||||
|
ssid: !secret wifi_ssid
|
||||||
|
password: !secret wifi_password
|
||||||
|
fast_connect: True
|
||||||
|
domain: .cloonar.smart
|
||||||
|
|
||||||
|
# Enable fallback hotspot (captive portal) in case wifi connection fails
|
||||||
|
ap:
|
||||||
|
ssid: "Presense-Kitchen Fallback"
|
||||||
|
password: "jMTo5YkCC01q"
|
||||||
|
|
||||||
|
captive_portal:
|
||||||
|
|
||||||
|
bluetooth_proxy:
|
||||||
|
|
||||||
55
esphome/presense-office.yaml
Normal file
55
esphome/presense-office.yaml
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
esphome:
|
||||||
|
name: presense-office
|
||||||
|
friendly_name: presense-office
|
||||||
|
|
||||||
|
esp32:
|
||||||
|
board: esp32dev
|
||||||
|
framework:
|
||||||
|
type: esp-idf
|
||||||
|
|
||||||
|
# Enable logging
|
||||||
|
logger:
|
||||||
|
|
||||||
|
# Enable Home Assistant API
|
||||||
|
api:
|
||||||
|
|
||||||
|
ota:
|
||||||
|
- platform: esphome
|
||||||
|
|
||||||
|
wifi:
|
||||||
|
ssid: !secret wifi_ssid
|
||||||
|
password: !secret wifi_password
|
||||||
|
fast_connect: True
|
||||||
|
domain: .cloonar.smart
|
||||||
|
|
||||||
|
# Enable fallback hotspot (captive portal) in case wifi connection fails
|
||||||
|
ap:
|
||||||
|
ssid: "Presense-Office Fallback Hotspot"
|
||||||
|
password: "jMTo5YkCC01q"
|
||||||
|
|
||||||
|
captive_portal:
|
||||||
|
|
||||||
|
bluetooth_proxy:
|
||||||
|
|
||||||
|
external_components:
|
||||||
|
- source: github://koying/esphome-ble-remote@master
|
||||||
|
components: [ ble_client_hid ]
|
||||||
|
|
||||||
|
ble_client:
|
||||||
|
- id: ble_client_1
|
||||||
|
mac_address: "90:f8:2e:f9:d7:32" # Replace with your remote's MAC address
|
||||||
|
|
||||||
|
ble_client_hid:
|
||||||
|
- id: ble_client_hid_1
|
||||||
|
ble_client_id: ble_client_1
|
||||||
|
|
||||||
|
sensor:
|
||||||
|
- platform: ble_client_hid
|
||||||
|
type: last_event_value
|
||||||
|
name: "Last Event Value"
|
||||||
|
ble_client_hid_id: ble_client_hid_1
|
||||||
|
|
||||||
|
text_sensor:
|
||||||
|
- platform: ble_client_hid
|
||||||
|
name: "Last Event Usage"
|
||||||
|
ble_client_hid_id: ble_client_hid_1
|
||||||
68
esphome/toilet-bulb.yaml
Normal file
68
esphome/toilet-bulb.yaml
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
substitutions:
|
||||||
|
device_name: "toilet-bulb"
|
||||||
|
friendly_name: "Toilet Bulb"
|
||||||
|
|
||||||
|
esphome:
|
||||||
|
name: ${device_name}
|
||||||
|
comment: ${friendly_name}
|
||||||
|
on_boot:
|
||||||
|
then:
|
||||||
|
- light.turn_on:
|
||||||
|
id: my_light
|
||||||
|
- delay: 100ms
|
||||||
|
- light.turn_on:
|
||||||
|
id: my_light
|
||||||
|
brightness: 20%
|
||||||
|
- delay: 100ms
|
||||||
|
- light.turn_on:
|
||||||
|
id: my_light
|
||||||
|
color_temperature: 2700 K
|
||||||
|
|
||||||
|
esp8266:
|
||||||
|
board: esp01_1m
|
||||||
|
|
||||||
|
interval:
|
||||||
|
- interval: 15s
|
||||||
|
then:
|
||||||
|
- if:
|
||||||
|
condition:
|
||||||
|
api.connected: # check if api connected
|
||||||
|
else:
|
||||||
|
- light.turn_on:
|
||||||
|
id: my_light
|
||||||
|
brightness: 100%
|
||||||
|
- delay: 100ms
|
||||||
|
- light.turn_on:
|
||||||
|
id: my_light
|
||||||
|
color_temperature: 6500 K
|
||||||
|
|
||||||
|
|
||||||
|
# Enable Home Assistant API
|
||||||
|
api:
|
||||||
|
batch_delay: 0ms
|
||||||
|
|
||||||
|
ota:
|
||||||
|
platform: esphome
|
||||||
|
|
||||||
|
wifi:
|
||||||
|
ssid: !secret wifi_ssid
|
||||||
|
password: !secret wifi_password
|
||||||
|
fast_connect: True
|
||||||
|
domain: .cloonar.smart
|
||||||
|
|
||||||
|
output:
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
id: warm_white
|
||||||
|
pin: GPIO4
|
||||||
|
- platform: esp8266_pwm
|
||||||
|
id: brightness
|
||||||
|
pin: GPIO5
|
||||||
|
|
||||||
|
light:
|
||||||
|
- platform: cwww
|
||||||
|
id: my_light
|
||||||
|
name: ${friendly_name}
|
||||||
|
warm_white: warm_white
|
||||||
|
cold_white: brightness
|
||||||
|
cold_white_color_temperature: 6500 K
|
||||||
|
warm_white_color_temperature: 2700 K
|
||||||
26
fleet.nix
26
fleet.nix
@@ -19,38 +19,42 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
users = [
|
users = [
|
||||||
{
|
|
||||||
username = "web-01.cloonar.com";
|
|
||||||
key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCl7cvUGMmtpVfJ3PB4Rco7V8z83nivst77SgBn+Z3cHgcDJDu9l3L4Q6rv9b6thmEX+Xf0ri6UwDI8UuJro4F9qpCXsTkHres3f/pDZokgfO7bvU2l7ujq6NnAx0qJWdB6oku36x3t2wBnvkDijXLtGPeQbd6c33hECEwA7QszvoBbGi0yFiGsqR5W7o0kiju/LMzCkExeaspFV6DBtEW0qZVMYx+lBIK5Hi/g3vBjbhFdWGz8T2AITcAnGI9n6f+dg3dlMPEHXnF9KRod1EVDnYMxbEp49i98m65F1xAFwOo35WSg48LlV1PK1VusboE3pHgE2VEFmW1J+PVQZ+z0JAaRBv/wSVN0YzuCLfLtUr10K1W23YbT1UVm7FusKpT1KElZ9adfbk6SXVhXnru40VcwqgYfw7naQJzT8aDI9Tnci+z4xCCxrdUF/psDBPD5sfjMPbjdPbt6Jnx1H9ZodiC/sQUtbn6MMbenMSf/AmuUC9xzpXlqCtPmN1dSC+8= root@web-01";
|
|
||||||
}
|
|
||||||
{
|
{
|
||||||
username = "web-arm";
|
username = "web-arm";
|
||||||
key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGzJRWe8hsqAVnGSjPrcheloteWMzORoQ5Gj4IfhCROF";
|
key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGzJRWe8hsqAVnGSjPrcheloteWMzORoQ5Gj4IfhCROF";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
username = "mail.cloonar.com";
|
username = "mail";
|
||||||
key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCfEuRazRv8zKWJSq+T3SssgOrkBFu6y/t6uoMNrD3P9WHowRDejo2rBsWFgPszhfgxLpWHiuSZFMG8z+07k5fVTdmbUwx0vXI1lmQ7AxB/CPwBef2Vpb7b8Rq6geejvP8X6UjQWP0rsCMtoX2SeBDTG8bDlyq1U3vYxVY4hery6a9Wu57OI5VbSIHhqQvExo7euz8V7ORsLyT8gi9x3r8gNaKJmvssB6QXXZ7U2sJaAUjhV/BmrZJD5qR9EwqwiMPJ2+SkZ0Vz6CFG6GLyB/ngXPEfclLKK7AzookJy7WepqojjFTzmOBMH903oR+MIpjDECKxgaFtW4xY0A/tj8ZDCBPtP8AKjediOASkAi7eUMPseQKDE0BNLSidC0hlQUe0aPaMeA8b1U86PblzpgF8ntkUPbxhO0AgHKq9fPN+f58f75fryNbhgPRRkeLet1q3hxguEMg2MIg/EqIw862YPWPtGRk0wJHwQU7jx+9BbjdptAVTJo/Cj9vM7mpZphE= root@mail";
|
key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCfEuRazRv8zKWJSq+T3SssgOrkBFu6y/t6uoMNrD3P9WHowRDejo2rBsWFgPszhfgxLpWHiuSZFMG8z+07k5fVTdmbUwx0vXI1lmQ7AxB/CPwBef2Vpb7b8Rq6geejvP8X6UjQWP0rsCMtoX2SeBDTG8bDlyq1U3vYxVY4hery6a9Wu57OI5VbSIHhqQvExo7euz8V7ORsLyT8gi9x3r8gNaKJmvssB6QXXZ7U2sJaAUjhV/BmrZJD5qR9EwqwiMPJ2+SkZ0Vz6CFG6GLyB/ngXPEfclLKK7AzookJy7WepqojjFTzmOBMH903oR+MIpjDECKxgaFtW4xY0A/tj8ZDCBPtP8AKjediOASkAi7eUMPseQKDE0BNLSidC0hlQUe0aPaMeA8b1U86PblzpgF8ntkUPbxhO0AgHKq9fPN+f58f75fryNbhgPRRkeLet1q3hxguEMg2MIg/EqIw862YPWPtGRk0wJHwQU7jx+9BbjdptAVTJo/Cj9vM7mpZphE= root@mail";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
username = "nb-01.cloonar.com";
|
username = "nb";
|
||||||
key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7";
|
key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJ6g/lXONzSW1JbyXnj+/0QPWtaiNxu9A0GOCbi96603";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
username = "nb-new.cloonar.com";
|
username = "nb-new";
|
||||||
key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIC1dDoAJUY58I+4SSfDAkO5kInsMcJT/r/mW+MYXLQVR";
|
key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIC1dDoAJUY58I+4SSfDAkO5kInsMcJT/r/mW+MYXLQVR";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
username = "fw.cloonar.com";
|
username = "fw";
|
||||||
key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDtxpJAFohRtBaET9e7EE4I6UmeUT/h1ZTD1zeOHFiWB/AT71ooDT4/QukJOA3LqklDjtDQHH+qjGY50Wa8/oGTA/X3aBDPg5GAHN+U+kYO2UTC69VVjh4TTS35ijg+AdgegtMI4c0VIUMZB24tthV9KEbD20w6XnTzy2Q6PjbBrwsOeHYr9pkygJZDU65ZeKmLyR6yLaadHzXX1I7V2SwiakPEebhQaGipm540d+tAbirKCHcmiORkpd++e3dfwi25hC9bCQ7b3bdaFPAmuhhFEid4jpCt79X+l0qqpClgRLziBjYykNJDFKAljFBJA11/3ofPCuaBCDUuJVhAH044gtT3sbvJq1prd8ElZy6L1yc5YbfFgDMwi71Y2hef780NmDs5Opk9xUCKqdl1YfLyUDgdiiaZ8uhUMd2Ai9BAxJAXtcz/V41ngt3YkUVyGTZdTAODIKk44blGIkgs7JO4yam4UB1curbD0faIZnWLyS5pdFQ+FI05YVjoHXJdme8=";
|
key = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDtxpJAFohRtBaET9e7EE4I6UmeUT/h1ZTD1zeOHFiWB/AT71ooDT4/QukJOA3LqklDjtDQHH+qjGY50Wa8/oGTA/X3aBDPg5GAHN+U+kYO2UTC69VVjh4TTS35ijg+AdgegtMI4c0VIUMZB24tthV9KEbD20w6XnTzy2Q6PjbBrwsOeHYr9pkygJZDU65ZeKmLyR6yLaadHzXX1I7V2SwiakPEebhQaGipm540d+tAbirKCHcmiORkpd++e3dfwi25hC9bCQ7b3bdaFPAmuhhFEid4jpCt79X+l0qqpClgRLziBjYykNJDFKAljFBJA11/3ofPCuaBCDUuJVhAH044gtT3sbvJq1prd8ElZy6L1yc5YbfFgDMwi71Y2hef780NmDs5Opk9xUCKqdl1YfLyUDgdiiaZ8uhUMd2Ai9BAxJAXtcz/V41ngt3YkUVyGTZdTAODIKk44blGIkgs7JO4yam4UB1curbD0faIZnWLyS5pdFQ+FI05YVjoHXJdme8=";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
username = "fw-new";
|
username = "fw-new";
|
||||||
key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILnb9todh2b+c3iCmEz72smRwL37aZf3Xs3voT7+PLTP";
|
key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILnb9todh2b+c3iCmEz72smRwL37aZf3Xs3voT7+PLTP";
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
username = "gpd-win4";
|
||||||
|
key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILjfS2DtS8PQgkf86dU+EVu5t+r/QlCWmY7+RPYprQrO";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
username = "nas";
|
||||||
|
key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICS6b97LPUpr7/kWvOcI40s5e+gfbfz0I2/hAPL6zTmU";
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
username = "mail.social-grow.tech";
|
username = "amzebs-01";
|
||||||
key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH1K4mhBji1kMGnO55OOFaDknBf2Q6wgm7DaMYKip+S5";
|
key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINMkFZ60SPl8pzEtGrFq1+n6ZkDuNe3xJaccJMjr3y/q";
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
in {
|
in {
|
||||||
|
|||||||
57
gpd-win-4.md
Normal file
57
gpd-win-4.md
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
I want a wall-mounted docking solution for my GPD Win 4, designed in OpenSCAD 2021.1. Here are the requirements and clarifications:
|
||||||
|
|
||||||
|
Orientation & Fit
|
||||||
|
|
||||||
|
The GPD Win 4 should be inserted upside down (top facing down), with the screen facing the wall.
|
||||||
|
It slides in from the top and is guided by side rails.
|
||||||
|
There should be a small clearance so the GPD Win 4 can be easily inserted/removed without excessive friction.
|
||||||
|
Front Rail (Lip)
|
||||||
|
|
||||||
|
Side Rails:
|
||||||
|
The dock should have two side rails that run from top to bottom, guiding the GPD Win 4.
|
||||||
|
|
||||||
|
The front is open for airflow.
|
||||||
|
However, there should be a small lip (front rail) on each side, running from top to bottom and connected to the side rails. This lip prevents the GPD Win 4 from falling out forward.
|
||||||
|
Back Plate / Wall Mount
|
||||||
|
|
||||||
|
The dock has a solid back plate that mounts to the wall with two countersunk screws.
|
||||||
|
The default spacing and size of these screws can be parameterized (e.g., an M4 or M3 countersunk hole).
|
||||||
|
The back plate thickness should be sufficient for strength (e.g., 3–4 mm).
|
||||||
|
No special side or back vents are needed.
|
||||||
|
Cable Brackets
|
||||||
|
|
||||||
|
At the bottom, back, inside the dock, there are two brackets, one for a 90° USB-C cable (standard USB-C power) and one for a 90° Oculink flat cable.
|
||||||
|
The back plate should be open where these two brackets are, so the cables can exit the dock.
|
||||||
|
Each bracket should have:
|
||||||
|
An opening on the side facing the wall, to allow the cable to pass behind (i.e., into or through the wall).
|
||||||
|
A hole for an M3 screw that presses against the cable from the side to lock it in place.
|
||||||
|
Enough space to seat a 90° connector so it points upwards to plug into the GPD Win 4.
|
||||||
|
Parametric Design
|
||||||
|
|
||||||
|
The design should be fully parameterized in OpenSCAD, including (but not limited to) the following parameters:
|
||||||
|
device_width, device_thickness, device_length (for the GPD Win 4)
|
||||||
|
clearance_x, clearance_y, clearance_z (how much extra space around the device)
|
||||||
|
wall_plate_thickness
|
||||||
|
rail_thickness
|
||||||
|
front_rail_lip_width or front_rail_lip_thickness
|
||||||
|
wall_mount_screw_hole_diameter, wall_mount_screw_spacing (for countersunk screws)
|
||||||
|
bracket_inner_width_usbC, bracket_inner_height_usbC (for the USB-C connector dimensions)
|
||||||
|
bracket_inner_width_oculink, bracket_inner_height_oculink (for the Oculink connector dimensions)
|
||||||
|
m3_side_screw_hole_diameter (the hole that lets an M3 screw clamp the cable from the side)
|
||||||
|
Any other geometry parameters (openings for cables, bracket thickness, etc.)
|
||||||
|
Defaults
|
||||||
|
|
||||||
|
Please choose default dimensions that accurately reflect:
|
||||||
|
Approximate GPD Win 4 size (if not exact, then close estimates).
|
||||||
|
Standard 90° USB-C and 90° Oculink connector sizes.
|
||||||
|
Typical M3 screws for cable clamps.
|
||||||
|
Countersunk holes for M3 or M4 wall screws (whichever you prefer).
|
||||||
|
Version
|
||||||
|
|
||||||
|
This must render successfully in OpenSCAD 2021.1.
|
||||||
|
Summary
|
||||||
|
|
||||||
|
The final output should be an OpenSCAD file that, when the parameters are set to their defaults, produces the described wall-mounted docking station for the GPD Win 4 with side rails, minimal front lip, bracket cutouts for cables, and properly sized holes for screws.
|
||||||
|
|
||||||
|
If any additional measurements or details are needed, please ask.
|
||||||
|
|
||||||
471
hosts/amzebs-01/EMAIL_SETUP.md
Normal file
471
hosts/amzebs-01/EMAIL_SETUP.md
Normal file
@@ -0,0 +1,471 @@
|
|||||||
|
# Email Setup for amzebs-01 (amz.at)
|
||||||
|
|
||||||
|
This host is configured to send emails via Laravel with DKIM signing.
|
||||||
|
|
||||||
|
## Configuration Overview
|
||||||
|
|
||||||
|
- **Postfix**: Localhost-only SMTP server (no external access)
|
||||||
|
- **Rspamd**: DKIM signing with host-specific key
|
||||||
|
- **Domain**: amz.at
|
||||||
|
- **DKIM Selector**: amzebs-01
|
||||||
|
- **Secret Management**: DKIM private key stored in sops
|
||||||
|
|
||||||
|
## Initial Setup (Before First Deployment)
|
||||||
|
|
||||||
|
### 1. Generate DKIM Key Pair
|
||||||
|
|
||||||
|
You need to generate a DKIM key pair locally first. You'll need `rspamd` package installed.
|
||||||
|
|
||||||
|
#### Option A: Using rspamd (if installed locally)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create a temporary directory
|
||||||
|
mkdir -p /tmp/dkim-gen
|
||||||
|
|
||||||
|
# Generate the key pair
|
||||||
|
rspamadm dkim_keygen -s amzebs-01 -d amz.at -k /tmp/dkim-gen/amz.at.amzebs-01.key
|
||||||
|
```
|
||||||
|
|
||||||
|
This will output:
|
||||||
|
- **Private key** saved to `/tmp/dkim-gen/amz.at.amzebs-01.key`
|
||||||
|
- **Public key** printed to stdout (starts with `v=DKIM1; k=rsa; p=...`)
|
||||||
|
|
||||||
|
#### Option B: Using OpenSSL (alternative)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create temporary directory
|
||||||
|
mkdir -p /tmp/dkim-gen
|
||||||
|
|
||||||
|
# Generate private key (2048-bit RSA)
|
||||||
|
openssl genrsa -out /tmp/dkim-gen/amz.at.amzebs-01.key 2048
|
||||||
|
|
||||||
|
# Extract public key in the correct format for DNS
|
||||||
|
openssl rsa -in /tmp/dkim-gen/amz.at.amzebs-01.key -pubout -outform PEM | \
|
||||||
|
grep -v '^-----' | tr -d '\n' > /tmp/dkim-gen/public.txt
|
||||||
|
|
||||||
|
# Display the DNS record value
|
||||||
|
echo "v=DKIM1; k=rsa; p=$(cat /tmp/dkim-gen/public.txt)"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Save the public key output!** You'll need it for DNS configuration later.
|
||||||
|
|
||||||
|
### 2. Add DKIM Private Key to Sops Secrets
|
||||||
|
|
||||||
|
Now you need to encrypt and add the private key to your secrets file.
|
||||||
|
|
||||||
|
#### Step 1: View the private key
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cat /tmp/dkim-gen/amz.at.amzebs-01.key
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Step 2: Edit the secrets file
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /home/dominik/projects/cloonar/cloonar-nixos/hosts/amzebs-01
|
||||||
|
sops secrets.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Step 3: Add the key to secrets.yaml
|
||||||
|
|
||||||
|
In the sops editor, add a new key called `rspamd-dkim-key` with the **entire private key content** including the BEGIN/END markers:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
rspamd-dkim-key: |
|
||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC...
|
||||||
|
(paste the entire key content here)
|
||||||
|
...
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
|
```
|
||||||
|
|
||||||
|
**Important:**
|
||||||
|
- Make sure to use the pipe `|` character for multiline content
|
||||||
|
- Keep the proper indentation (2 spaces before each line of the key)
|
||||||
|
- Include the full BEGIN/END markers
|
||||||
|
|
||||||
|
#### Step 4: Save and exit
|
||||||
|
|
||||||
|
Save the file in sops (it will be encrypted automatically).
|
||||||
|
|
||||||
|
#### Step 5: Clean up temporary files
|
||||||
|
|
||||||
|
```bash
|
||||||
|
rm -rf /tmp/dkim-gen
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Verify Secret is Encrypted
|
||||||
|
|
||||||
|
Check that the secret is properly encrypted:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cat hosts/amzebs-01/secrets.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
You should see encrypted content, not the plain private key.
|
||||||
|
|
||||||
|
### 4. Extract Public Key for DNS (if needed later)
|
||||||
|
|
||||||
|
If you didn't save the public key earlier, you can extract it after deployment:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# On the server after deployment
|
||||||
|
sudo cat /var/lib/rspamd/dkim/amz.at.amzebs-01.key | \
|
||||||
|
openssl rsa -pubout -outform PEM 2>/dev/null | \
|
||||||
|
grep -v '^-----' | tr -d '\n'
|
||||||
|
```
|
||||||
|
|
||||||
|
Then format it as:
|
||||||
|
```
|
||||||
|
v=DKIM1; k=rsa; p=<output_from_above>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Deployment
|
||||||
|
|
||||||
|
### 1. Deploy Configuration
|
||||||
|
|
||||||
|
After adding the DKIM private key to sops, deploy the configuration:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build and switch on the remote host
|
||||||
|
nixos-rebuild switch --flake .#amzebs-01 --target-host amzebs-01 --use-remote-sudo
|
||||||
|
```
|
||||||
|
|
||||||
|
Or if deploying locally on the server:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo nixos-rebuild switch
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Verify Deployment
|
||||||
|
|
||||||
|
Check that the services are running:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check rspamd-dkim-setup service
|
||||||
|
systemctl status rspamd-dkim-setup
|
||||||
|
|
||||||
|
# Check that rspamd is running
|
||||||
|
systemctl status rspamd
|
||||||
|
|
||||||
|
# Check that postfix is running
|
||||||
|
systemctl status postfix
|
||||||
|
|
||||||
|
# Verify DKIM key was deployed
|
||||||
|
ls -la /var/lib/rspamd/dkim/amz.at.amzebs-01.key
|
||||||
|
```
|
||||||
|
|
||||||
|
## DNS Configuration
|
||||||
|
|
||||||
|
Add the following DNS records to ensure proper email delivery and avoid spam classification.
|
||||||
|
|
||||||
|
### Critical: PTR Record (Reverse DNS)
|
||||||
|
|
||||||
|
**This is CRITICAL for email deliverability!** Without a proper PTR record, most mail servers will reject or spam your emails.
|
||||||
|
|
||||||
|
#### What is a PTR Record?
|
||||||
|
A PTR (pointer) record is a reverse DNS entry that maps your IP address back to your hostname. Mail servers use this to verify you're a legitimate mail server.
|
||||||
|
|
||||||
|
#### Required PTR Record
|
||||||
|
```
|
||||||
|
IP Address: 23.88.38.1
|
||||||
|
Points to: amzebs-01.amz.at
|
||||||
|
```
|
||||||
|
|
||||||
|
#### How to Configure PTR Record
|
||||||
|
|
||||||
|
**Step 1: Contact Your Hosting Provider**
|
||||||
|
|
||||||
|
PTR records MUST be configured through your hosting provider (e.g., Hetzner, OVH, AWS, etc.). You cannot set PTR records through your domain registrar.
|
||||||
|
|
||||||
|
1. Log into your hosting provider's control panel
|
||||||
|
2. Find the "Reverse DNS" or "PTR Record" section
|
||||||
|
3. Set the PTR record for IP `23.88.38.1` to point to `amzebs-01.amz.at`
|
||||||
|
|
||||||
|
**Common Provider Links:**
|
||||||
|
- **Hetzner**: Robot panel → IPs → Edit reverse DNS
|
||||||
|
- **OVH**: Network → IP → ... → Modify reverse
|
||||||
|
- **AWS EC2**: Select instance → Networking → Request reverse DNS
|
||||||
|
|
||||||
|
**Step 2: Verify Forward DNS First**
|
||||||
|
|
||||||
|
Before setting the PTR record, ensure your forward DNS is correct:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# This should return 23.88.38.1
|
||||||
|
dig +short amzebs-01.amz.at A
|
||||||
|
host amzebs-01.amz.at
|
||||||
|
```
|
||||||
|
|
||||||
|
**Step 3: Verify PTR Record**
|
||||||
|
|
||||||
|
After configuring, verify the PTR record is working:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Method 1: Using dig
|
||||||
|
dig +short -x 23.88.38.1
|
||||||
|
|
||||||
|
# Method 2: Using host
|
||||||
|
host 23.88.38.1
|
||||||
|
|
||||||
|
# Method 3: Using nslookup
|
||||||
|
nslookup 23.88.38.1
|
||||||
|
```
|
||||||
|
|
||||||
|
All commands should return: `amzebs-01.amz.at`
|
||||||
|
|
||||||
|
**Step 4: Verify FCrDNS (Forward-Confirmed Reverse DNS)**
|
||||||
|
|
||||||
|
This ensures forward and reverse DNS match properly:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Forward lookup
|
||||||
|
dig +short amzebs-01.amz.at
|
||||||
|
# Should output: 23.88.38.1
|
||||||
|
|
||||||
|
# Reverse lookup
|
||||||
|
dig +short -x 23.88.38.1
|
||||||
|
# Should output: amzebs-01.amz.at.
|
||||||
|
```
|
||||||
|
|
||||||
|
If both work correctly, FCrDNS passes! ✓
|
||||||
|
|
||||||
|
**Why PTR Records Matter:**
|
||||||
|
- Gmail, Microsoft, Yahoo require valid PTR records
|
||||||
|
- Missing PTR = automatic spam classification or rejection
|
||||||
|
- Can add 5-10 points to spam score alone
|
||||||
|
- Required for professional email delivery
|
||||||
|
|
||||||
|
### Domain DNS Records (amz.at)
|
||||||
|
|
||||||
|
Add these records through your domain registrar's DNS management:
|
||||||
|
|
||||||
|
#### SPF Record
|
||||||
|
```
|
||||||
|
Type: TXT
|
||||||
|
Name: @
|
||||||
|
Value: v=spf1 mx a:amzebs-01.amz.at ~all
|
||||||
|
```
|
||||||
|
|
||||||
|
#### DKIM Record
|
||||||
|
```
|
||||||
|
Type: TXT
|
||||||
|
Name: amzebs-01._domainkey
|
||||||
|
Value: [Your public key from step 1 above]
|
||||||
|
```
|
||||||
|
|
||||||
|
The DKIM record will look something like:
|
||||||
|
```
|
||||||
|
v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...
|
||||||
|
```
|
||||||
|
|
||||||
|
#### DMARC Record
|
||||||
|
```
|
||||||
|
Type: TXT
|
||||||
|
Name: _dmarc
|
||||||
|
Value: v=DMARC1; p=quarantine; rua=mailto:postmaster@amz.at; ruf=mailto:postmaster@amz.at; fo=1
|
||||||
|
```
|
||||||
|
|
||||||
|
**Explanation:**
|
||||||
|
- `p=quarantine`: Failed messages should be quarantined (you can change to `p=reject` after testing)
|
||||||
|
- `rua=mailto:...`: Aggregate reports sent to this address
|
||||||
|
- `ruf=mailto:...`: Forensic reports sent to this address
|
||||||
|
- `fo=1`: Generate forensic reports for any failure
|
||||||
|
|
||||||
|
## Laravel Configuration
|
||||||
|
|
||||||
|
Update your Laravel application's `.env` file:
|
||||||
|
|
||||||
|
#### Option A: Using sendmail (Recommended)
|
||||||
|
```env
|
||||||
|
MAIL_MAILER=sendmail
|
||||||
|
MAIL_FROM_ADDRESS=noreply@amz.at
|
||||||
|
MAIL_FROM_NAME="${APP_NAME}"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Option B: Using SMTP
|
||||||
|
```env
|
||||||
|
MAIL_MAILER=smtp
|
||||||
|
MAIL_HOST=127.0.0.1
|
||||||
|
MAIL_PORT=25
|
||||||
|
MAIL_USERNAME=null
|
||||||
|
MAIL_PASSWORD=null
|
||||||
|
MAIL_ENCRYPTION=null
|
||||||
|
MAIL_FROM_ADDRESS=noreply@amz.at
|
||||||
|
MAIL_FROM_NAME="${APP_NAME}"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note**: Laravel can use ANY email address with @amz.at domain. All will be DKIM signed automatically.
|
||||||
|
|
||||||
|
## Testing Email
|
||||||
|
|
||||||
|
### Test from Command Line
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Send a test email
|
||||||
|
echo "Test email body" | mail -s "Test Subject" test@example.com -aFrom:test@amz.at
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check Postfix Queue
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# View mail queue
|
||||||
|
mailq
|
||||||
|
|
||||||
|
# View logs
|
||||||
|
journalctl -u postfix -f
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check Rspamd Logs
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# View rspamd logs
|
||||||
|
journalctl -u rspamd -f
|
||||||
|
```
|
||||||
|
|
||||||
|
### Test DKIM Signature and Deliverability
|
||||||
|
|
||||||
|
Send an email to test your complete email configuration:
|
||||||
|
|
||||||
|
#### Email Testing Services
|
||||||
|
1. **Mail Tester** (https://www.mail-tester.com/)
|
||||||
|
- Provides a temporary email address
|
||||||
|
- Shows comprehensive spam score (0-10, higher is better)
|
||||||
|
- Checks DKIM, SPF, DMARC, PTR, blacklists, content
|
||||||
|
- **Target: 9/10 or higher**
|
||||||
|
|
||||||
|
2. **MXToolbox Email Health** (https://mxtoolbox.com/emailhealth/)
|
||||||
|
- Comprehensive deliverability check
|
||||||
|
- Checks DNS records, blacklists, configuration
|
||||||
|
|
||||||
|
3. **Google Admin Toolbox** (https://toolbox.googleapps.com/apps/messageheader/)
|
||||||
|
- Paste email headers to see how Gmail scored your email
|
||||||
|
- Shows SPF, DKIM, DMARC results
|
||||||
|
|
||||||
|
#### What to Check
|
||||||
|
- ✓ DKIM signature is valid
|
||||||
|
- ✓ SPF passes
|
||||||
|
- ✓ DMARC passes
|
||||||
|
- ✓ PTR record (reverse DNS) matches
|
||||||
|
- ✓ Not on any blacklists
|
||||||
|
- ✓ Spam score < 2.0 (lower is better)
|
||||||
|
|
||||||
|
#### Common Issues & Fixes
|
||||||
|
|
||||||
|
**High Spam Score (> 5.0)**
|
||||||
|
- Check: PTR record configured correctly? (Critical!)
|
||||||
|
- Check: HELO name matches hostname?
|
||||||
|
- Check: All headers present (To:, From:, Subject:)?
|
||||||
|
- Check: IP not blacklisted?
|
||||||
|
|
||||||
|
**Missing "To:" Header**
|
||||||
|
Your Laravel app must set a recipient. In your code:
|
||||||
|
```php
|
||||||
|
Mail::to('recipient@example.com')
|
||||||
|
->send(new YourMailable());
|
||||||
|
```
|
||||||
|
|
||||||
|
**HELO/EHLO Mismatch**
|
||||||
|
After applying this configuration, HELO should be `amzebs-01.amz.at`, not `localhost`
|
||||||
|
|
||||||
|
**Check Current HELO Name**
|
||||||
|
```bash
|
||||||
|
# On the server
|
||||||
|
echo "HELO test" | nc localhost 25
|
||||||
|
# Should see: 250 amzebs-01.amz.at
|
||||||
|
```
|
||||||
|
|
||||||
|
## Verification Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check if Postfix is running
|
||||||
|
systemctl status postfix
|
||||||
|
|
||||||
|
# Check if Rspamd is running
|
||||||
|
systemctl status rspamd
|
||||||
|
|
||||||
|
# Check if Postfix is listening on localhost only
|
||||||
|
ss -tlnp | grep master
|
||||||
|
|
||||||
|
# View DKIM public key again
|
||||||
|
systemctl start rspamd-show-dkim
|
||||||
|
journalctl -u rspamd-show-dkim
|
||||||
|
|
||||||
|
# Check if DKIM key exists
|
||||||
|
ls -la /var/lib/rspamd/dkim/
|
||||||
|
```
|
||||||
|
|
||||||
|
## Security Notes
|
||||||
|
|
||||||
|
1. **Localhost-only**: Postfix is configured to listen ONLY on 127.0.0.1
|
||||||
|
2. **No authentication**: Not needed since only local processes can connect
|
||||||
|
3. **No firewall changes**: No external ports opened for email
|
||||||
|
4. **DKIM signing**: All outgoing emails are automatically signed with DKIM
|
||||||
|
5. **Host-specific key**: Using selector "amzebs-01" allows multiple hosts to send for amz.at
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Email not being sent
|
||||||
|
|
||||||
|
1. Check Postfix status: `systemctl status postfix`
|
||||||
|
2. Check queue: `mailq`
|
||||||
|
3. Check logs: `journalctl -u postfix -n 100`
|
||||||
|
|
||||||
|
### DKIM not signing
|
||||||
|
|
||||||
|
1. Check Rspamd status: `systemctl status rspamd`
|
||||||
|
2. Check if key exists: `ls -la /var/lib/rspamd/dkim/amz.at.amzebs-01.key`
|
||||||
|
3. Check Rspamd logs: `journalctl -u rspamd -n 100`
|
||||||
|
|
||||||
|
### Permission errors
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Ensure proper ownership
|
||||||
|
chown -R rspamd:rspamd /var/lib/rspamd/dkim/
|
||||||
|
chmod 600 /var/lib/rspamd/dkim/*.key
|
||||||
|
```
|
||||||
|
|
||||||
|
### Rotate DKIM key
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. Generate new key pair locally (follow "Initial Setup" steps)
|
||||||
|
# 2. Update the rspamd-dkim-key in secrets.yaml with new key
|
||||||
|
# 3. Deploy the configuration
|
||||||
|
nixos-rebuild switch
|
||||||
|
|
||||||
|
# 4. Restart the setup service to copy new key
|
||||||
|
systemctl restart rspamd-dkim-setup
|
||||||
|
|
||||||
|
# 5. Restart rspamd to use new key
|
||||||
|
systemctl restart rspamd
|
||||||
|
|
||||||
|
# 6. Update DNS with new public key
|
||||||
|
# 7. Wait for DNS propagation before removing old DNS record
|
||||||
|
```
|
||||||
|
|
||||||
|
## Related Files
|
||||||
|
|
||||||
|
- Postfix config: `hosts/amzebs-01/modules/postfix.nix`
|
||||||
|
- Rspamd config: `hosts/amzebs-01/modules/rspamd.nix`
|
||||||
|
- Main config: `hosts/amzebs-01/configuration.nix`
|
||||||
|
- Secrets file: `hosts/amzebs-01/secrets.yaml` (encrypted)
|
||||||
|
|
||||||
|
## Sops Secret Configuration
|
||||||
|
|
||||||
|
The DKIM private key is stored as a sops secret with the following configuration:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
sops.secrets.rspamd-dkim-key = {
|
||||||
|
owner = "rspamd";
|
||||||
|
group = "rspamd";
|
||||||
|
mode = "0400";
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
This ensures:
|
||||||
|
- Only the rspamd user can read the key
|
||||||
|
- The key is decrypted at boot time by sops-nix
|
||||||
|
- The key is encrypted in version control
|
||||||
|
- The key persists across rebuilds
|
||||||
|
|
||||||
|
The key is automatically copied from the sops secret path to `/var/lib/rspamd/dkim/amz.at.amzebs-01.key` by the `rspamd-dkim-setup.service` on every boot.
|
||||||
1
hosts/amzebs-01/channel
Normal file
1
hosts/amzebs-01/channel
Normal file
@@ -0,0 +1 @@
|
|||||||
|
https://channels.nixos.org/nixos-25.11
|
||||||
81
hosts/amzebs-01/configuration.nix
Normal file
81
hosts/amzebs-01/configuration.nix
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
{ config, lib, pkgs, ... }: {
|
||||||
|
imports = [
|
||||||
|
./utils/bento.nix
|
||||||
|
./utils/modules/sops.nix
|
||||||
|
./utils/modules/nginx.nix
|
||||||
|
./utils/modules/set-nix-channel.nix
|
||||||
|
|
||||||
|
./modules/mysql.nix
|
||||||
|
./modules/web/stack.nix
|
||||||
|
./modules/laravel-storage.nix
|
||||||
|
./modules/laravel-scheduler.nix
|
||||||
|
./modules/blackbox-exporter.nix
|
||||||
|
./modules/postfix.nix
|
||||||
|
./modules/rspamd.nix
|
||||||
|
|
||||||
|
./utils/modules/autoupgrade.nix
|
||||||
|
./utils/modules/promtail
|
||||||
|
./utils/modules/victoriametrics
|
||||||
|
./utils/modules/borgbackup.nix
|
||||||
|
|
||||||
|
./hardware-configuration.nix
|
||||||
|
|
||||||
|
./sites
|
||||||
|
];
|
||||||
|
|
||||||
|
environment.systemPackages = with pkgs; [
|
||||||
|
vim
|
||||||
|
screen
|
||||||
|
php82
|
||||||
|
];
|
||||||
|
|
||||||
|
time.timeZone = "Europe/Vienna";
|
||||||
|
|
||||||
|
sops.age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
|
||||||
|
sops.defaultSopsFile = ./secrets.yaml;
|
||||||
|
|
||||||
|
nix.gc = {
|
||||||
|
automatic = true;
|
||||||
|
options = "--delete-older-than 60d";
|
||||||
|
};
|
||||||
|
|
||||||
|
boot.tmp.cleanOnBoot = true;
|
||||||
|
zramSwap.enable = true;
|
||||||
|
|
||||||
|
networking.hostName = "amzebs-01";
|
||||||
|
networking.domain = "cloonar.com";
|
||||||
|
|
||||||
|
services.openssh.enable = true;
|
||||||
|
users.users.root.openssh.authorizedKeys.keys = [
|
||||||
|
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7"
|
||||||
|
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFshMhXwS0FQFPlITipshvNKrV8sA52ZFlnaoHd1thKg"
|
||||||
|
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIRQuPqH5fdX3KEw7DXzWEdO3AlUn1oSmtJtHB71ICoH Generated By Termius"
|
||||||
|
];
|
||||||
|
|
||||||
|
programs.ssh = {
|
||||||
|
knownHosts = {
|
||||||
|
"git.cloonar.com" = {
|
||||||
|
publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDlUj7eEfS/4+z/3IhFhOTXAfpGEpNv6UWuYSL5OAhus";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# backups - adjust repo for this host
|
||||||
|
borgbackup.repo = "u149513-sub10@u149513-sub10.your-backup.de:borg";
|
||||||
|
|
||||||
|
# Use HTTP-01 challenge for Let's Encrypt (not DNS)
|
||||||
|
security.acme.acceptTerms = true;
|
||||||
|
security.acme.defaults.email = "admin+acme@cloonar.com";
|
||||||
|
|
||||||
|
networking.firewall = {
|
||||||
|
enable = true;
|
||||||
|
allowedTCPPorts = [ 22 80 443 3306 ];
|
||||||
|
|
||||||
|
# Allow MariaDB access only from specific IP
|
||||||
|
extraCommands = ''
|
||||||
|
iptables -A nixos-fw -p tcp --dport 3306 -s 77.119.230.30 -j nixos-fw-accept
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
system.stateVersion = "25.11";
|
||||||
|
}
|
||||||
27
hosts/amzebs-01/hardware-configuration.nix
Normal file
27
hosts/amzebs-01/hardware-configuration.nix
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# Hardware configuration for amzebs-01
|
||||||
|
# This is a template - update with actual hardware configuration after installation
|
||||||
|
{ modulesPath, ... }:
|
||||||
|
{
|
||||||
|
imports = [ (modulesPath + "/profiles/qemu-guest.nix") ];
|
||||||
|
|
||||||
|
boot.loader.grub = {
|
||||||
|
efiSupport = true;
|
||||||
|
efiInstallAsRemovable = true;
|
||||||
|
device = "nodev";
|
||||||
|
configurationLimit = 2;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Update these with actual device UUIDs and paths after installation
|
||||||
|
fileSystems."/boot" = {
|
||||||
|
device = "/dev/sda15";
|
||||||
|
fsType = "vfat";
|
||||||
|
};
|
||||||
|
|
||||||
|
fileSystems."/" = {
|
||||||
|
device = "/dev/sda1";
|
||||||
|
fsType = "ext4";
|
||||||
|
};
|
||||||
|
|
||||||
|
boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "xen_blkfront" ];
|
||||||
|
boot.initrd.kernelModules = [ "nvme" ];
|
||||||
|
}
|
||||||
83
hosts/amzebs-01/modules/blackbox-exporter.nix
Normal file
83
hosts/amzebs-01/modules/blackbox-exporter.nix
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
{ config, pkgs, lib, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
hostname = config.networking.hostName;
|
||||||
|
|
||||||
|
cfg = config.services.blackbox-exporter;
|
||||||
|
nginxVHosts = config.services.nginx.virtualHosts or {};
|
||||||
|
allDomains = lib.attrNames nginxVHosts;
|
||||||
|
filteredDomains = builtins.filter (d: !builtins.elem d cfg.blacklistDomains) allDomains;
|
||||||
|
httpsDomains = lib.map (d: "https://${d}") filteredDomains;
|
||||||
|
domainsString = builtins.concatStringsSep "\n "
|
||||||
|
(map (d: "\"${d}\",") httpsDomains);
|
||||||
|
in {
|
||||||
|
options.services.blackbox-exporter.blacklistDomains = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [];
|
||||||
|
description = "List of domains to exclude from Blackbox Exporter monitoring";
|
||||||
|
};
|
||||||
|
|
||||||
|
config = {
|
||||||
|
services.blackbox-exporter = {
|
||||||
|
blacklistDomains = [
|
||||||
|
# Currently no domains blacklisted - monitoring all nginx virtualHosts
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
# Systemd service for Blackbox Exporter
|
||||||
|
systemd.services.blackbox-exporter = {
|
||||||
|
description = "Blackbox Exporter";
|
||||||
|
after = [ "network-online.target" ];
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
serviceConfig.ExecStart = ''
|
||||||
|
${pkgs.prometheus-blackbox-exporter}/bin/blackbox_exporter \
|
||||||
|
--config.file=/etc/blackbox_exporter/blackbox.yml
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
# Configuration file for Blackbox Exporter
|
||||||
|
environment.etc."blackbox_exporter/blackbox.yml".text = ''
|
||||||
|
modules:
|
||||||
|
http_200_final:
|
||||||
|
prober: http
|
||||||
|
http:
|
||||||
|
method: GET
|
||||||
|
follow_redirects: true
|
||||||
|
preferred_ip_protocol: "ip4" # avoid blanket IPv6 failures
|
||||||
|
valid_http_versions: ["HTTP/1.1", "HTTP/2.0"]
|
||||||
|
valid_status_codes: [200]
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Add scrape config for VictoriaMetrics agent
|
||||||
|
services.victoriametrics.extraScrapeConfigs = [
|
||||||
|
''
|
||||||
|
- job_name: "blackbox_http_all_domains"
|
||||||
|
metrics_path: "/probe"
|
||||||
|
params:
|
||||||
|
module: ["http_200_final"]
|
||||||
|
|
||||||
|
static_configs:
|
||||||
|
- targets:
|
||||||
|
[
|
||||||
|
${domainsString}
|
||||||
|
]
|
||||||
|
|
||||||
|
relabel_configs:
|
||||||
|
- source_labels: ["__address__"]
|
||||||
|
target_label: "__param_target"
|
||||||
|
regex: '(.*)'
|
||||||
|
replacement: "$1"
|
||||||
|
- source_labels: ["__param_target"]
|
||||||
|
target_label: "instance"
|
||||||
|
- target_label: "__address__"
|
||||||
|
replacement: "127.0.0.1:9115"
|
||||||
|
- source_labels: ["__address__"]
|
||||||
|
regex: "127\\.0\\.0\\.1:9115"
|
||||||
|
target_label: "__scheme__"
|
||||||
|
replacement: "http"
|
||||||
|
''
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
51
hosts/amzebs-01/modules/laravel-scheduler.nix
Normal file
51
hosts/amzebs-01/modules/laravel-scheduler.nix
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
# Daily scheduled Laravel artisan jobs
|
||||||
|
# Runs artisan finish:reports at 01:00 for production and staging APIs
|
||||||
|
|
||||||
|
let
|
||||||
|
php = pkgs.php82;
|
||||||
|
|
||||||
|
sites = [
|
||||||
|
{
|
||||||
|
domain = "api.ebs.amz.at";
|
||||||
|
user = "api_ebs_amz_at";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
domain = "api.stage.ebs.amz.at";
|
||||||
|
user = "api_stage_ebs_amz_at";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
mkArtisanService = site: {
|
||||||
|
name = "artisan-finish-reports-${site.domain}";
|
||||||
|
value = {
|
||||||
|
description = "Laravel artisan finish:reports for ${site.domain}";
|
||||||
|
after = [ "network.target" "mysql.service" "phpfpm-${site.domain}.service" ];
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
User = site.user;
|
||||||
|
Group = "nginx";
|
||||||
|
WorkingDirectory = "/var/www/${site.domain}";
|
||||||
|
ExecStart = "${php}/bin/php artisan finish:reports";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
mkArtisanTimer = site: {
|
||||||
|
name = "artisan-finish-reports-${site.domain}";
|
||||||
|
value = {
|
||||||
|
description = "Daily timer for artisan finish:reports on ${site.domain}";
|
||||||
|
wantedBy = [ "timers.target" ];
|
||||||
|
timerConfig = {
|
||||||
|
OnCalendar = "*-*-* 01:00:00";
|
||||||
|
Persistent = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
in
|
||||||
|
{
|
||||||
|
systemd.services = builtins.listToAttrs (map mkArtisanService sites);
|
||||||
|
systemd.timers = builtins.listToAttrs (map mkArtisanTimer sites);
|
||||||
|
}
|
||||||
30
hosts/amzebs-01/modules/laravel-storage.nix
Normal file
30
hosts/amzebs-01/modules/laravel-storage.nix
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
# Create Laravel storage directories for all API instances
|
||||||
|
# These directories are required for Laravel to function properly
|
||||||
|
systemd.tmpfiles.rules = [
|
||||||
|
# api.ebs.cloonar.dev
|
||||||
|
"d /var/www/api.ebs.cloonar.dev/storage/framework/cache 0775 api_ebs_cloonar_dev nginx -"
|
||||||
|
"d /var/www/api.ebs.cloonar.dev/storage/framework/testing 0775 api_ebs_cloonar_dev nginx -"
|
||||||
|
"d /var/www/api.ebs.cloonar.dev/storage/framework/sessions 0775 api_ebs_cloonar_dev nginx -"
|
||||||
|
"d /var/www/api.ebs.cloonar.dev/storage/framework/views 0775 api_ebs_cloonar_dev nginx -"
|
||||||
|
"d /var/www/api.ebs.cloonar.dev/storage/logs 0775 api_ebs_cloonar_dev nginx -"
|
||||||
|
"d /var/www/api.ebs.cloonar.dev/bootstrap/cache 0775 api_ebs_cloonar_dev nginx -"
|
||||||
|
|
||||||
|
# api.ebs.amz.at
|
||||||
|
"d /var/www/api.ebs.amz.at/storage/framework/cache 0775 api_ebs_amz_at nginx -"
|
||||||
|
"d /var/www/api.ebs.amz.at/storage/framework/testing 0775 api_ebs_amz_at nginx -"
|
||||||
|
"d /var/www/api.ebs.amz.at/storage/framework/sessions 0775 api_ebs_amz_at nginx -"
|
||||||
|
"d /var/www/api.ebs.amz.at/storage/framework/views 0775 api_ebs_amz_at nginx -"
|
||||||
|
"d /var/www/api.ebs.amz.at/storage/logs 0775 api_ebs_amz_at nginx -"
|
||||||
|
"d /var/www/api.ebs.amz.at/bootstrap/cache 0775 api_ebs_amz_at nginx -"
|
||||||
|
|
||||||
|
# api.stage.ebs.amz.at
|
||||||
|
"d /var/www/api.stage.ebs.amz.at/storage/framework/cache 0775 api_stage_ebs_amz_at nginx -"
|
||||||
|
"d /var/www/api.stage.ebs.amz.at/storage/framework/testing 0775 api_stage_ebs_amz_at nginx -"
|
||||||
|
"d /var/www/api.stage.ebs.amz.at/storage/framework/sessions 0775 api_stage_ebs_amz_at nginx -"
|
||||||
|
"d /var/www/api.stage.ebs.amz.at/storage/framework/views 0775 api_stage_ebs_amz_at nginx -"
|
||||||
|
"d /var/www/api.stage.ebs.amz.at/storage/logs 0775 api_stage_ebs_amz_at nginx -"
|
||||||
|
"d /var/www/api.stage.ebs.amz.at/bootstrap/cache 0775 api_stage_ebs_amz_at nginx -"
|
||||||
|
];
|
||||||
|
}
|
||||||
43
hosts/amzebs-01/modules/mysql.nix
Normal file
43
hosts/amzebs-01/modules/mysql.nix
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
{ pkgs, config, ... }:
|
||||||
|
{
|
||||||
|
|
||||||
|
services.mysql = {
|
||||||
|
enable = true;
|
||||||
|
package = pkgs.mariadb;
|
||||||
|
settings = {
|
||||||
|
mysqld = {
|
||||||
|
max_allowed_packet = "64M";
|
||||||
|
transaction_isolation = "READ-COMMITTED";
|
||||||
|
binlog_format = "ROW";
|
||||||
|
# Allow remote connections
|
||||||
|
bind-address = "0.0.0.0";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Create read-only user for remote access after MySQL starts
|
||||||
|
systemd.services.mysql-setup-readonly-user = {
|
||||||
|
description = "Setup MySQL read-only user";
|
||||||
|
after = [ "mysql.service" ];
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
RemainAfterExit = true;
|
||||||
|
User = "root";
|
||||||
|
};
|
||||||
|
script = ''
|
||||||
|
PASSWORD=$(cat ${config.sops.secrets.mysql-readonly-password.path})
|
||||||
|
${pkgs.mariadb}/bin/mysql -u root <<EOF
|
||||||
|
CREATE USER IF NOT EXISTS 'api_ebs_amz_at_ro'@'%' IDENTIFIED BY '$PASSWORD';
|
||||||
|
GRANT SELECT ON api_ebs_amz_at.* TO 'api_ebs_amz_at_ro'@'%';
|
||||||
|
FLUSH PRIVILEGES;
|
||||||
|
EOF
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
services.mysqlBackup.enable = true;
|
||||||
|
|
||||||
|
sops.secrets.mysql-readonly-password = {
|
||||||
|
owner = "mysql";
|
||||||
|
};
|
||||||
|
}
|
||||||
56
hosts/amzebs-01/modules/postfix.nix
Normal file
56
hosts/amzebs-01/modules/postfix.nix
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
{ pkgs
|
||||||
|
, lib
|
||||||
|
, config
|
||||||
|
, ...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
headerChecksFile = pkgs.writeText "header_checks" ''
|
||||||
|
# Warn about missing critical headers (but don't reject from localhost)
|
||||||
|
# These help identify misconfigured applications
|
||||||
|
/^$/ WARN Missing headers detected
|
||||||
|
'';
|
||||||
|
in
|
||||||
|
{
|
||||||
|
services.postfix = {
|
||||||
|
mapFiles."header_checks" = headerChecksFile;
|
||||||
|
enable = true;
|
||||||
|
hostname = "amzebs-01.amz.at";
|
||||||
|
domain = "amz.at";
|
||||||
|
|
||||||
|
config = {
|
||||||
|
# Explicitly set hostname to prevent "localhost" HELO issues
|
||||||
|
myhostname = "amzebs-01.amz.at";
|
||||||
|
|
||||||
|
# Set proper HELO name for outgoing SMTP connections
|
||||||
|
smtp_helo_name = "amzebs-01.amz.at";
|
||||||
|
|
||||||
|
# Professional SMTP banner (prevents appearing as default/misconfigured)
|
||||||
|
smtpd_banner = "$myhostname ESMTP";
|
||||||
|
|
||||||
|
# Listen only on localhost for security
|
||||||
|
# Laravel will send via localhost, no external access needed
|
||||||
|
inet_interfaces = "loopback-only";
|
||||||
|
|
||||||
|
# Compatibility
|
||||||
|
compatibility_level = "2";
|
||||||
|
|
||||||
|
# Only accept mail from localhost
|
||||||
|
mynetworks = [ "127.0.0.0/8" "[::1]/128" ];
|
||||||
|
|
||||||
|
# Larger message size limits for attachments
|
||||||
|
mailbox_size_limit = 202400000; # ~200MB
|
||||||
|
message_size_limit = 51200000; # ~50MB
|
||||||
|
|
||||||
|
# Ensure proper header handling
|
||||||
|
# Reject mail that's missing critical headers
|
||||||
|
header_checks = "regexp:/var/lib/postfix/conf/header_checks";
|
||||||
|
|
||||||
|
# Rate limiting to prevent spam-like behavior
|
||||||
|
# Allow reasonable sending rates for applications
|
||||||
|
smtpd_client_message_rate_limit = 100;
|
||||||
|
smtpd_client_recipient_rate_limit = 200;
|
||||||
|
|
||||||
|
# Milter configuration is handled automatically by rspamd.postfix.enable
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
84
hosts/amzebs-01/modules/rspamd.nix
Normal file
84
hosts/amzebs-01/modules/rspamd.nix
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
{ pkgs
|
||||||
|
, config
|
||||||
|
, ...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
domain = "amz.at";
|
||||||
|
selector = "amzebs-01";
|
||||||
|
|
||||||
|
localConfig = pkgs.writeText "local.conf" ''
|
||||||
|
logging {
|
||||||
|
level = "notice";
|
||||||
|
}
|
||||||
|
|
||||||
|
# DKIM signing configuration with host-specific selector
|
||||||
|
dkim_signing {
|
||||||
|
path = "/var/lib/rspamd/dkim/${domain}.${selector}.key";
|
||||||
|
selector = "${selector}";
|
||||||
|
allow_username_mismatch = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
# ARC signing (Authenticated Received Chain)
|
||||||
|
arc {
|
||||||
|
path = "/var/lib/rspamd/dkim/${domain}.${selector}.key";
|
||||||
|
selector = "${selector}";
|
||||||
|
allow_username_mismatch = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Add authentication results to headers
|
||||||
|
milter_headers {
|
||||||
|
use = ["authentication-results"];
|
||||||
|
authenticated_headers = ["authentication-results"];
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
in
|
||||||
|
{
|
||||||
|
services.rspamd = {
|
||||||
|
enable = true;
|
||||||
|
extraConfig = ''
|
||||||
|
.include(priority=1,duplicate=merge) "${localConfig}"
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Enable Postfix milter integration
|
||||||
|
postfix.enable = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Copy DKIM key from sops secret to rspamd directory
|
||||||
|
systemd.services.rspamd-dkim-setup = {
|
||||||
|
description = "Setup DKIM key from sops secret for ${domain}";
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
before = [ "rspamd.service" ];
|
||||||
|
after = [ "sops-nix.service" ];
|
||||||
|
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
RemainAfterExit = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
script = ''
|
||||||
|
DKIM_DIR="/var/lib/rspamd/dkim"
|
||||||
|
DKIM_KEY="$DKIM_DIR/${domain}.${selector}.key"
|
||||||
|
|
||||||
|
# Create directory if it doesn't exist
|
||||||
|
mkdir -p "$DKIM_DIR"
|
||||||
|
|
||||||
|
# Copy key from sops secret
|
||||||
|
if [ -f "${config.sops.secrets.rspamd-dkim-key.path}" ]; then
|
||||||
|
cp "${config.sops.secrets.rspamd-dkim-key.path}" "$DKIM_KEY"
|
||||||
|
chown rspamd:rspamd "$DKIM_KEY"
|
||||||
|
chmod 600 "$DKIM_KEY"
|
||||||
|
echo "DKIM key deployed successfully from sops secret"
|
||||||
|
else
|
||||||
|
echo "ERROR: DKIM key not found in sops secrets!"
|
||||||
|
echo "Please ensure rspamd-dkim-key is defined in secrets.yaml"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
sops.secrets.rspamd-dkim-key = {
|
||||||
|
owner = "rspamd";
|
||||||
|
group = "rspamd";
|
||||||
|
mode = "0400";
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -53,6 +53,7 @@ let
|
|||||||
|
|
||||||
enableMysql = mkEnableOption (lib.mdDoc "MySQL Database");
|
enableMysql = mkEnableOption (lib.mdDoc "MySQL Database");
|
||||||
enableDefaultLocations = mkEnableOption (lib.mdDoc "Create default nginx location directives") // { default = true; };
|
enableDefaultLocations = mkEnableOption (lib.mdDoc "Create default nginx location directives") // { default = true; };
|
||||||
|
enablePhp = mkEnableOption (lib.mdDoc "PHP-FPM support") // { default = true; };
|
||||||
|
|
||||||
authorizedKeys = mkOption {
|
authorizedKeys = mkOption {
|
||||||
type = types.listOf types.str;
|
type = types.listOf types.str;
|
||||||
@@ -138,12 +139,12 @@ in
|
|||||||
BindPaths = "BindPaths=/var/www/${domain}:/var/www/${domain}";
|
BindPaths = "BindPaths=/var/www/${domain}:/var/www/${domain}";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
) cfg.instances;
|
) (lib.filterAttrs (name: opts: opts.enablePhp) cfg.instances);
|
||||||
|
|
||||||
services.phpfpm.pools = mapAttrs' (instance: instanceOpts:
|
services.phpfpm.pools = mapAttrs' (instance: instanceOpts:
|
||||||
let
|
let
|
||||||
domain = if instanceOpts.domain != null then instanceOpts.domain else instance;
|
domain = if instanceOpts.domain != null then instanceOpts.domain else instance;
|
||||||
user = if instanceOpts.user != null
|
user = if instanceOpts.user != null
|
||||||
then instanceOps.user
|
then instanceOps.user
|
||||||
else builtins.replaceStrings ["." "-"] ["_" "_"] domain;
|
else builtins.replaceStrings ["." "-"] ["_" "_"] domain;
|
||||||
in
|
in
|
||||||
@@ -166,7 +167,7 @@ in
|
|||||||
phpPackage = instanceOpts.phpPackage;
|
phpPackage = instanceOpts.phpPackage;
|
||||||
phpEnv."PATH" = pkgs.lib.makeBinPath [ instanceOpts.phpPackage ];
|
phpEnv."PATH" = pkgs.lib.makeBinPath [ instanceOpts.phpPackage ];
|
||||||
}
|
}
|
||||||
) cfg.instances;
|
) (lib.filterAttrs (name: opts: opts.enablePhp) cfg.instances);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -216,7 +217,7 @@ in
|
|||||||
'';
|
'';
|
||||||
|
|
||||||
# Cache Media: images, icons, video, audio, HTC
|
# Cache Media: images, icons, video, audio, HTC
|
||||||
"~* \\.(?:jpg|jpeg|gif|png|webp|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc|woff2)$".extraConfig = ''
|
"~* \\.(?:css|js|jpg|jpeg|gif|png|webp|avif|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc|woff2)$".extraConfig = ''
|
||||||
expires 1y;
|
expires 1y;
|
||||||
access_log off;
|
access_log off;
|
||||||
add_header Cache-Control "public";
|
add_header Cache-Control "public";
|
||||||
@@ -228,19 +229,12 @@ in
|
|||||||
add_header Cache-Control "public";
|
add_header Cache-Control "public";
|
||||||
'';
|
'';
|
||||||
|
|
||||||
# Cache CSS, Javascript, Images, Icons, Video, Audio, HTC, Fonts
|
|
||||||
"~* \\.(?:css|js|jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc|woff2)$".extraConfig = ''
|
|
||||||
expires 1y;
|
|
||||||
access_log off;
|
|
||||||
add_header Cache-Control "public";
|
|
||||||
'';
|
|
||||||
|
|
||||||
"/".extraConfig = ''
|
"/".extraConfig = ''
|
||||||
index index.php index.html;
|
index index.php index.html;
|
||||||
try_files $uri $uri/ /index.php$is_args$args;
|
try_files $uri $uri/ /index.php$is_args$args;
|
||||||
'';
|
'';
|
||||||
})
|
})
|
||||||
{
|
(mkIf instanceOpts.enablePhp {
|
||||||
"~ [^/]\\.php(/|$)".extraConfig = ''
|
"~ [^/]\\.php(/|$)".extraConfig = ''
|
||||||
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
|
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
|
||||||
if (!-f $document_root$fastcgi_script_name) {
|
if (!-f $document_root$fastcgi_script_name) {
|
||||||
@@ -256,7 +250,7 @@ in
|
|||||||
fastcgi_pass unix:${config.services.phpfpm.pools."${domain}".socket};
|
fastcgi_pass unix:${config.services.phpfpm.pools."${domain}".socket};
|
||||||
fastcgi_index index.php;
|
fastcgi_index index.php;
|
||||||
'';
|
'';
|
||||||
}
|
})
|
||||||
];
|
];
|
||||||
|
|
||||||
extraConfig = instanceOpts.extraConfig;
|
extraConfig = instanceOpts.extraConfig;
|
||||||
@@ -325,4 +319,3 @@ config.users.groups = mapAttrs' (instance: instanceOpts:
|
|||||||
mkIf instanceOpts.enableMysql user
|
mkIf instanceOpts.enableMysql user
|
||||||
) cfg.instances;
|
) cfg.instances;
|
||||||
}
|
}
|
||||||
|
|
||||||
46
hosts/amzebs-01/secrets.yaml
Normal file
46
hosts/amzebs-01/secrets.yaml
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
borg-passphrase: ENC[AES256_GCM,data:Q2GvEat5EHmshFiya3yNqFTVS+oJv0al+bYMRwysb0yu7F2gCJd000Y3ibA+tUPSL9iSlMSy0cTkesGVEGBt9w==,iv:/kUJXgibF1cyaCPB55/0nKYq9sSva6psxu2P/l7iRN4=,tag:velr9LTfoj7gEWhUmvPtQg==,type:str]
|
||||||
|
borg-ssh-key: ENC[AES256_GCM,data:0YEvv7QDmGsur0PFMmz5HqDgDCEk0kRaOu1n7GGWAwmmr0K0bVbpKzHw5wMiMnXEBrvj0izo4P4LYGAlAAYn22Bhgi2eN/vdvSO5V5uDV1ep2dV/TN2m3oYgTIgot47YgwBhcNunIUtEsbZuhAsTGL6LFBPJ3OCLKvhXTNTDaajgH/e4CvyxHHl63MBzr0i1ajigl1IKCk2hhZF4Kd1YGBCVZRoNyyNXywihlcFeskNfldW/sd5Qn2nowVf1MEV9n6Il6Zc1FX69WUVy1k+kOT7HJZGq3uDmgwXQgQhqKm1wh5uOlLkGUX6fz/nz+YFzLFMuUVvs34CzbbEFuWmGU+aNQrfCfI1hqwB5s6wVNdpUmigX9AQMQklu85tHFJg1AaRvhA24Cp/GrptggrTThcjwVFoe9NSQouNYn+ImTvlsE4HuDRRFE6YUounGd2lpRd40LsEjwKiLtwBwqG94u4ZOI91+LG6ZqHftRehE9r/CtedLyqtluNyyQyUNKPraUOm9Rrapewsj0ZCZgGQU,iv:xdRUBQlZlwVIog5KgZRmGNxdmhFE9HgnK3Ahfo+zT9k=,tag:McsJKUEGnKXxiv8Tg5zA4A==,type:str]
|
||||||
|
mysql-readonly-password: ENC[AES256_GCM,data:k2RplkUZPGZlh29KXXdtwe+MCqKzTI/bLdyuEeicdkbGlBk1SGyLF8vW4t8=,iv:a14IrXYVCDqPKGfJSEPP8g19sPvRTx5NT8IVJJeL48s=,tag:GWgU3oa/+u21/L2y3+vOsw==,type:str]
|
||||||
|
rspamd-dkim-key: ENC[AES256_GCM,data:maOnsx8AQUIjXqHEzHLxtSvAkr9+YCZid9xWaflkffS0gHd/hoHrozHy+rHSjU7Mz7QHYhjUjFY7Hp7wdKQnHpQLJRV96iNPXTXXYtBr7oDL51cq8ozd094FuMeLNSPitV89OHDcM+9h1F4dsdDWPUiw7eoijQeZ8vx1/VCVAp4FVxTFX3qhoMhXlFabiyM85eKMwJG4BdSwqS624f2Z4tvECRp0pBGtd/3r4/EVRDV1qNsiFvH8mi8eyg9xiWDLDrePq4TuWSu1Xc7z0qpDy0o8iAwGhPu9egIyzHEPk07j9U7PpK56C2UCSY0JBm0hkBGbqLXyRklSMytxoKgw4GJykMwNPNXmA9yuLPanxagJB/z8b7X4HTuYhExzQcC6ke/y8xKcxU4qGt8Ayy5v+QoNpdqXIPsZkIuw9uWm6RIgDt2dCaOdI06lesZKjqU/T6EhDfGoGZX7DwQ7uV9xNDM4NW2jsKpUdFKnzPCCe7/jO/ck4P4i8V+6NWDjj4+/BXDNnKJbMcHIHoSvckCGZiginJsbGvSWd0HfbpR7GQAnL3uKB5/HuFAaUkx+dPHmmP2tOBv6vNt+tq+V9i4kQmwAdl8a9KI456tw9vLwXcBDZOO7n4X5H0jc4afoYCnvLxahvbIXm2QNcBYVKxkqBCvoYEMrBjrnujwbQdEfDKQf3g5p8LQwAfCQ3ng+XH/BDF3qMBdsN1u5Di0FQpCDaGKX8pJ1gg+il76fJgSU8ftoaT32hJnLAjal4cgNIxbta2UYQLixUqaWZ8xqvxrSopkWYrlBBUyQh9jMEoTzpxwCsEPQ72qgVcQfJYlMl4WUBwcasfJnySR+qZ22g3fhStpAQ2HuTGhLjTG1QOewYdwDXDhNmcbqZ478Sp1t7qbBx0R7vWFSyYCMlbmLmvzPm6Z3ET7lkfCrMjMNXaQ8cWSF19QaHAfqRwQooLL93yx7U0KHCilEg4bUjsw8MLQNa4A0ohpq6CG4s5O1+di7W4/h71/moggIebFb2eGLJ8BvbkwiVozXI9L77IGd9RswlEjZed18u7fqetS7dyDthhVG2pvya4zZI/cxIq6oJkNr2RIt3NgYChOh0I/17DuSJJ1jAmPB0Evj8QtCCo49ENnyO5cGWn12DZWybwYkg2jQC4aDFA/u5ajTo3wOKdwHj5hgMz/z05Bn2vAdhCGl6uWWNzcNnDiu3/rjqsjOkfkp0hCP7Q==,iv:FORxJ8htcoLIEJihUN7im3dN4jhnigB70InTohtpWwU=,tag:e2DHBd2dn3piCkEdkbHdoA==,type:str]
|
||||||
|
sops:
|
||||||
|
age:
|
||||||
|
- recipient: age14grjcxaq4h55yfnjxvnqhtswxhj9sfdcvyas4lwvpa8py27pjy2sv3g6v7
|
||||||
|
enc: |
|
||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBhQUpWNUgxVnhuTXd2TkF0
|
||||||
|
SVVHemFKRWlYczZ0TnBESVNRczhuRUNnUG1BCmJKQ2JZbHhFcXJidHJzci9OaFBm
|
||||||
|
ZTd0MGhsaVBic3dMb3psUHRCRnR3ODQKLS0tIERrSG1GVTRHdkJpVWpqdTZ4Yytq
|
||||||
|
OHhlZjV6MjRVbXFsWjlQSU03ZDNwYm8KAswHRSdV0BW/oJyZx63iZRHsF7SZ6PO+
|
||||||
|
hajQqmEyfcVfEu39zZzxQ2mtWlOr69I++irOhE3NeiFeJ1yIRQDJEQ==
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
|
- recipient: age1exny8unxynaw03yu8ppahu5z28uermghr8ag34e7kdqnaduq9stsyettzz
|
||||||
|
enc: |
|
||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBUaUNnY0hpdDAzMTNIUS9D
|
||||||
|
RmdKbmplUk9DRXlLRXEvSnVjT05sQjcvTnpJCkd6bGRINm5yYUZOUTVzWEdjRmtG
|
||||||
|
Mmx0ci93N2wvTWV5MzlRVnlYdUxoUWsKLS0tIEVHUlNWYStWTG01RzRrVnNXc3BW
|
||||||
|
VkRkUXROU3plNmwvTUVhYmhCS2syQkEKKgC0EmUu1u2vZ/SZTnam+h846gZSyY4V
|
||||||
|
JyMzkws8O5TY9juWdDzXJIU67mIgc4qrWWN3uh8k28JBZGc078b5bg==
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
|
- recipient: age1v6p8dan2t3w9h94fz4flldl32082j3s9x6zqq7u5j66keth9aphsd6pvch
|
||||||
|
enc: |
|
||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBoK2JUNVdYTzkvM1BBWXRm
|
||||||
|
citCNlE4Z1NLdEZ2R0tNZTVSMlFSeGxGOURnClJnYURYa0JZaVprQWdBcmVnOWVj
|
||||||
|
TGVCK1JWMVlueHJUaTZZYmROM0E5aDAKLS0tIEJxYkdadGtZM250d2d6Ujl2UU9C
|
||||||
|
YUpkVll2S2RpT0I1UVZiZFRKS1prMEEKp/bGImanJ/58vTQG/gUun/Y2QdmOEi3h
|
||||||
|
hVS0V2QcfuGgi0/YofLOM3+M6k6ViXw07XfXmR+puvLIHKr2y11x1Q==
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
|
- recipient: age1xcgc6u7fmc2trgxtdtf5nhrd7axzweuxlg0ya9jre3sdrg6c6easecue9w
|
||||||
|
enc: |
|
||||||
|
-----BEGIN AGE ENCRYPTED FILE-----
|
||||||
|
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBDSGdEZnZEaDRpWUJVcnds
|
||||||
|
VGFSQklvczBZdEdEbXhodW8vME9wMUpVRENjClFZcnVqYkJxdlBiZFhma0tmZjgz
|
||||||
|
YXlIdlRDTDU4MHg1dzhGVDRJb2FGYVUKLS0tIDBXSWZ2NkxzdEk0ZlFRM00ybFNy
|
||||||
|
M0doaWl5R2cwU2RxQm5DbWxXeTZ5S2MKwrB3SysmgzCThQOhEVx18dxIfko0+oZY
|
||||||
|
9BSZOoFbfuwiLbtpL4J8bzxDvxn6sXxB8EBJH1hbpID53AquWDsxSw==
|
||||||
|
-----END AGE ENCRYPTED FILE-----
|
||||||
|
lastmodified: "2025-11-19T11:16:25Z"
|
||||||
|
mac: ENC[AES256_GCM,data:x4yor9G+QirceSYSX1K9GdfyGellT4JCkE09Tl9/mOX8HMOKFAQGknuwwU6SNGg+ciBFk4TdjQnDmVai4T8JQo9W/DLiZ+GKnWO3s+ZLDX30sEF0aMjKa43R5CCPO/Fl2XH96TaPC+8itTJQ6TpBSg51QLPcpqrMljiBNWvEoTU=,iv:Zi9rglAwgsejUmIpLN/1QlL80BSp3HP32k1xkWt2b+o=,tag:2ADk8d2G4OezkQjcV3CZuA==,type:str]
|
||||||
|
unencrypted_suffix: _unencrypted
|
||||||
|
version: 3.11.0
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
{ pkgs, lib, config, ... }:
|
{ pkgs, lib, config, ... }:
|
||||||
{
|
{
|
||||||
services.webstack.instances."api.paraclub.at" = {
|
services.webstack.instances."api.ebs.amz.at" = {
|
||||||
enableDefaultLocations = false;
|
enableDefaultLocations = false;
|
||||||
enableMysql = true;
|
enableMysql = true;
|
||||||
authorizedKeys = [
|
authorizedKeys = [
|
||||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCmLPJoHwL+d7dnc3aFLbRCDshxRSQ0dtAVv/LYBn2/PBlZcIyVO9drjr702GL9QuS5DQyjtoZjSOvv1ykBKedUwY3XDyyZgtqjleojKIFMXkdXtD5iG+RUraUfzcFCZU12BYXSeAXK1HmIjSDUtDOlp6lVVWxNpz1vWSRtA/+PULhP+n5Cj7232Wf372+EPfQPntOlcMbyrDLFtj7cUz+E6BH0qdX0l3QtIVnK/C1iagPAwLcwPJd9Sfs8lj5C4g8T9uBJa6OX+87lE4ySYY+Cik9BN59S0ctjXvWCFsPO3udQSC1mf33XdDenc2mbi+lZWTfrN8S2K5CsbxRsVBlbapFBRwufEpN4iQnaTu1QmzDrmktBFAPJ2jvjBJPIx6W3KOy3kUwh9WNhzd/ubf9dFTHzkTzgluo/Zk6/S8fTJiA4rbYKSkLw9Y265bvtR1kfUBLKSa/Axe5dkKysX1RNKfTJEwbh2TfIS3apQPZZc5kIEWfeK/6kbQX7WJZFtTs="
|
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBTsA1z6/vOshSqmEUGO6vFbAYCrucgNORMKyoQ5/9/l"
|
||||||
];
|
];
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
add_header X-Frame-Options "SAMEORIGIN";
|
add_header X-Frame-Options "SAMEORIGIN";
|
||||||
add_header X-Content-Type-Options "nosniff";
|
add_header X-Content-Type-Options "nosniff";
|
||||||
|
|
||||||
index index.php
|
index index.php;
|
||||||
|
|
||||||
charset utf-8;
|
charset utf-8;
|
||||||
|
|
||||||
@@ -31,4 +31,7 @@
|
|||||||
phpPackage = pkgs.php82.withExtensions ({ enabled, all }:
|
phpPackage = pkgs.php82.withExtensions ({ enabled, all }:
|
||||||
enabled ++ [ all.imagick ]);
|
enabled ++ [ all.imagick ]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Use HTTP-01 challenge for Let's Encrypt
|
||||||
|
services.nginx.virtualHosts."api.ebs.amz.at".acmeRoot = lib.mkForce "/var/lib/acme/acme-challenge";
|
||||||
}
|
}
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
{ pkgs, lib, config, ... }:
|
{ pkgs, lib, config, ... }:
|
||||||
{
|
{
|
||||||
services.webstack.instances."api.optiprot.eu" = {
|
services.webstack.instances."api.ebs.cloonar.dev" = {
|
||||||
enableDefaultLocations = false;
|
enableDefaultLocations = false;
|
||||||
enableMysql = true;
|
enableMysql = true;
|
||||||
authorizedKeys = [
|
authorizedKeys = [
|
||||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDDBGlzrg6NP5ezRFVu1CV8r0uCcS2oIgYG2/u6Cit++ARWQRO5Y0+9qC1Y2RNUaLPbvTmXg7ShskolUeuLryqvp10K2kXQ4E9NlmJ3BNLiAfWCzfe6gAgr6u5unVlXHttnP0leYpGGMUCKuiJpzy/bR6rMIUrCQC6W/MeXkwysNWKvL+ZD0IeQbogtfMFZmag9PO04RKZZvuUn9YvlgkTEK97g5dtyP1NxdtE9dDYf0G+0HcHITcw+lVmGNNwi43nAoUHieQd1kWc8YmxFB+y5O+vRH2O6pZBSdr0tdK6bPcezxd3Gk6i3a54yZfbvSislWA+o7s6uw/qExocpZb7xWa5ymPrGlEPbpYdT1y3hFO25+L1lR4QdG9oUNtJ974bL+EmYmHU+j32K3f8fxDg6BRo8FuriLtAzP7/2/7W8K4nIdMoosS+Ond2JE6XFkg1kSrXCivDBQoetZLO2y+ZPYcsQwIZsdjOnZqVr76nTepqCGIKYCuNM/9sl4AWCsyU="
|
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIqpF703JmLTBpBjTSvC0bnYu+lSYdmaGPHxMnHEbMmp"
|
||||||
];
|
];
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
add_header X-Frame-Options "SAMEORIGIN";
|
add_header X-Frame-Options "SAMEORIGIN";
|
||||||
add_header X-Content-Type-Options "nosniff";
|
add_header X-Content-Type-Options "nosniff";
|
||||||
|
|
||||||
index index.php
|
index index.php;
|
||||||
|
|
||||||
charset utf-8;
|
charset utf-8;
|
||||||
|
|
||||||
@@ -31,4 +31,7 @@
|
|||||||
phpPackage = pkgs.php82.withExtensions ({ enabled, all }:
|
phpPackage = pkgs.php82.withExtensions ({ enabled, all }:
|
||||||
enabled ++ [ all.imagick ]);
|
enabled ++ [ all.imagick ]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Use HTTP-01 challenge for Let's Encrypt
|
||||||
|
services.nginx.virtualHosts."api.ebs.cloonar.dev".acmeRoot = lib.mkForce "/var/lib/acme/acme-challenge";
|
||||||
}
|
}
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
{ pkgs, lib, config, ... }:
|
{ pkgs, lib, config, ... }:
|
||||||
{
|
{
|
||||||
services.webstack.instances."api.optiprot.cloonar.dev" = {
|
services.webstack.instances."api.stage.ebs.amz.at" = {
|
||||||
enableDefaultLocations = false;
|
enableDefaultLocations = false;
|
||||||
enableMysql = true;
|
enableMysql = true;
|
||||||
authorizedKeys = [
|
authorizedKeys = [
|
||||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDDBGlzrg6NP5ezRFVu1CV8r0uCcS2oIgYG2/u6Cit++ARWQRO5Y0+9qC1Y2RNUaLPbvTmXg7ShskolUeuLryqvp10K2kXQ4E9NlmJ3BNLiAfWCzfe6gAgr6u5unVlXHttnP0leYpGGMUCKuiJpzy/bR6rMIUrCQC6W/MeXkwysNWKvL+ZD0IeQbogtfMFZmag9PO04RKZZvuUn9YvlgkTEK97g5dtyP1NxdtE9dDYf0G+0HcHITcw+lVmGNNwi43nAoUHieQd1kWc8YmxFB+y5O+vRH2O6pZBSdr0tdK6bPcezxd3Gk6i3a54yZfbvSislWA+o7s6uw/qExocpZb7xWa5ymPrGlEPbpYdT1y3hFO25+L1lR4QdG9oUNtJ974bL+EmYmHU+j32K3f8fxDg6BRo8FuriLtAzP7/2/7W8K4nIdMoosS+Ond2JE6XFkg1kSrXCivDBQoetZLO2y+ZPYcsQwIZsdjOnZqVr76nTepqCGIKYCuNM/9sl4AWCsyU="
|
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIqpF703JmLTBpBjTSvC0bnYu+lSYdmaGPHxMnHEbMmp"
|
||||||
];
|
];
|
||||||
extraConfig = ''
|
extraConfig = ''
|
||||||
add_header X-Frame-Options "SAMEORIGIN";
|
add_header X-Frame-Options "SAMEORIGIN";
|
||||||
add_header X-Content-Type-Options "nosniff";
|
add_header X-Content-Type-Options "nosniff";
|
||||||
|
|
||||||
index index.php
|
index index.php;
|
||||||
|
|
||||||
charset utf-8;
|
charset utf-8;
|
||||||
|
|
||||||
@@ -31,4 +31,7 @@
|
|||||||
phpPackage = pkgs.php82.withExtensions ({ enabled, all }:
|
phpPackage = pkgs.php82.withExtensions ({ enabled, all }:
|
||||||
enabled ++ [ all.imagick ]);
|
enabled ++ [ all.imagick ]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Use HTTP-01 challenge for Let's Encrypt
|
||||||
|
services.nginx.virtualHosts."api.stage.ebs.amz.at".acmeRoot = lib.mkForce "/var/lib/acme/acme-challenge";
|
||||||
}
|
}
|
||||||
14
hosts/amzebs-01/sites/default.nix
Normal file
14
hosts/amzebs-01/sites/default.nix
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{ ... }: {
|
||||||
|
imports = [
|
||||||
|
# Enabled vhosts (cloonar.dev)
|
||||||
|
./api.ebs.cloonar.dev.nix
|
||||||
|
./ebs.cloonar.dev.nix
|
||||||
|
./ebs-mobile.cloonar.dev.nix
|
||||||
|
|
||||||
|
# Disabled vhosts (amz.at) - uncomment to enable
|
||||||
|
./api.ebs.amz.at.nix
|
||||||
|
./api.stage.ebs.amz.at.nix
|
||||||
|
./ebs.amz.at.nix
|
||||||
|
./stage.ebs.amz.at.nix
|
||||||
|
];
|
||||||
|
}
|
||||||
49
hosts/amzebs-01/sites/ebs-mobile.cloonar.dev.nix
Normal file
49
hosts/amzebs-01/sites/ebs-mobile.cloonar.dev.nix
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
{ pkgs, lib, config, ... }:
|
||||||
|
let
|
||||||
|
domain = "ebs-mobile.cloonar.dev";
|
||||||
|
dataDir = "/var/www/${domain}";
|
||||||
|
in {
|
||||||
|
services.nginx.virtualHosts."${domain}" = {
|
||||||
|
forceSSL = true;
|
||||||
|
enableACME = true;
|
||||||
|
# Use HTTP-01 challenge for Let's Encrypt
|
||||||
|
acmeRoot = lib.mkForce "/var/lib/acme/acme-challenge";
|
||||||
|
root = "${dataDir}";
|
||||||
|
|
||||||
|
locations."/favicon.ico".extraConfig = ''
|
||||||
|
log_not_found off;
|
||||||
|
access_log off;
|
||||||
|
'';
|
||||||
|
|
||||||
|
# React client-side routing support
|
||||||
|
locations."/".extraConfig = ''
|
||||||
|
index index.html;
|
||||||
|
try_files $uri $uri/ /index.html$is_args$args;
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Cache static assets
|
||||||
|
locations."~* \\.(js|jpg|gif|png|webp|css|woff2|svg|ico)$".extraConfig = ''
|
||||||
|
expires 365d;
|
||||||
|
add_header Pragma "public";
|
||||||
|
add_header Cache-Control "public";
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Deny PHP execution
|
||||||
|
locations."~ [^/]\\.php(/|$)".extraConfig = ''
|
||||||
|
deny all;
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
users.users."${domain}" = {
|
||||||
|
isNormalUser = true;
|
||||||
|
createHome = true;
|
||||||
|
home = dataDir;
|
||||||
|
homeMode = "770";
|
||||||
|
group = "nginx";
|
||||||
|
openssh.authorizedKeys.keys = [
|
||||||
|
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIErjoADQK5SJ5si/iezzwQn5xH1RkgnTIlbeE4BRU1FN"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
users.groups.${domain} = {};
|
||||||
|
}
|
||||||
49
hosts/amzebs-01/sites/ebs.amz.at.nix
Normal file
49
hosts/amzebs-01/sites/ebs.amz.at.nix
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
{ pkgs, lib, config, ... }:
|
||||||
|
let
|
||||||
|
domain = "ebs.amz.at";
|
||||||
|
dataDir = "/var/www/${domain}";
|
||||||
|
in {
|
||||||
|
services.nginx.virtualHosts."${domain}" = {
|
||||||
|
forceSSL = true;
|
||||||
|
enableACME = true;
|
||||||
|
# Use HTTP-01 challenge for Let's Encrypt
|
||||||
|
acmeRoot = lib.mkForce "/var/lib/acme/acme-challenge";
|
||||||
|
root = "${dataDir}";
|
||||||
|
|
||||||
|
locations."/favicon.ico".extraConfig = ''
|
||||||
|
log_not_found off;
|
||||||
|
access_log off;
|
||||||
|
'';
|
||||||
|
|
||||||
|
# React client-side routing support
|
||||||
|
locations."/".extraConfig = ''
|
||||||
|
index index.html;
|
||||||
|
try_files $uri $uri/ /index.html$is_args$args;
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Cache static assets
|
||||||
|
locations."~* \\.(js|jpg|gif|png|webp|css|woff2|svg|ico)$".extraConfig = ''
|
||||||
|
expires 365d;
|
||||||
|
add_header Pragma "public";
|
||||||
|
add_header Cache-Control "public";
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Deny PHP execution
|
||||||
|
locations."~ [^/]\\.php(/|$)".extraConfig = ''
|
||||||
|
deny all;
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
users.users."${domain}" = {
|
||||||
|
isNormalUser = true;
|
||||||
|
createHome = true;
|
||||||
|
home = dataDir;
|
||||||
|
homeMode = "770";
|
||||||
|
group = "nginx";
|
||||||
|
openssh.authorizedKeys.keys = [
|
||||||
|
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIInwmhTIPw7NnR3LDn2T5N6by0ZPXdL3r2O/8oRUc/ki"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
users.groups.${domain} = {};
|
||||||
|
}
|
||||||
49
hosts/amzebs-01/sites/ebs.cloonar.dev.nix
Normal file
49
hosts/amzebs-01/sites/ebs.cloonar.dev.nix
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
{ pkgs, lib, config, ... }:
|
||||||
|
let
|
||||||
|
domain = "ebs.cloonar.dev";
|
||||||
|
dataDir = "/var/www/${domain}";
|
||||||
|
in {
|
||||||
|
services.nginx.virtualHosts."${domain}" = {
|
||||||
|
forceSSL = true;
|
||||||
|
enableACME = true;
|
||||||
|
# Use HTTP-01 challenge for Let's Encrypt
|
||||||
|
acmeRoot = lib.mkForce "/var/lib/acme/acme-challenge";
|
||||||
|
root = "${dataDir}";
|
||||||
|
|
||||||
|
locations."/favicon.ico".extraConfig = ''
|
||||||
|
log_not_found off;
|
||||||
|
access_log off;
|
||||||
|
'';
|
||||||
|
|
||||||
|
# React client-side routing support
|
||||||
|
locations."/".extraConfig = ''
|
||||||
|
index index.html;
|
||||||
|
try_files $uri $uri/ /index.html$is_args$args;
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Cache static assets
|
||||||
|
locations."~* \\.(js|jpg|gif|png|webp|css|woff2|svg|ico)$".extraConfig = ''
|
||||||
|
expires 365d;
|
||||||
|
add_header Pragma "public";
|
||||||
|
add_header Cache-Control "public";
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Deny PHP execution
|
||||||
|
locations."~ [^/]\\.php(/|$)".extraConfig = ''
|
||||||
|
deny all;
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
users.users."${domain}" = {
|
||||||
|
isNormalUser = true;
|
||||||
|
createHome = true;
|
||||||
|
home = dataDir;
|
||||||
|
homeMode = "770";
|
||||||
|
group = "nginx";
|
||||||
|
openssh.authorizedKeys.keys = [
|
||||||
|
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIErjoADQK5SJ5si/iezzwQn5xH1RkgnTIlbeE4BRU1FN"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
users.groups.${domain} = {};
|
||||||
|
}
|
||||||
49
hosts/amzebs-01/sites/stage.ebs.amz.at.nix
Normal file
49
hosts/amzebs-01/sites/stage.ebs.amz.at.nix
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
{ pkgs, lib, config, ... }:
|
||||||
|
let
|
||||||
|
domain = "stage.ebs.amz.at";
|
||||||
|
dataDir = "/var/www/${domain}";
|
||||||
|
in {
|
||||||
|
services.nginx.virtualHosts."${domain}" = {
|
||||||
|
forceSSL = true;
|
||||||
|
enableACME = true;
|
||||||
|
# Use HTTP-01 challenge for Let's Encrypt
|
||||||
|
acmeRoot = lib.mkForce "/var/lib/acme/acme-challenge";
|
||||||
|
root = "${dataDir}";
|
||||||
|
|
||||||
|
locations."/favicon.ico".extraConfig = ''
|
||||||
|
log_not_found off;
|
||||||
|
access_log off;
|
||||||
|
'';
|
||||||
|
|
||||||
|
# React client-side routing support
|
||||||
|
locations."/".extraConfig = ''
|
||||||
|
index index.html;
|
||||||
|
try_files $uri $uri/ /index.html$is_args$args;
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Cache static assets
|
||||||
|
locations."~* \\.(js|jpg|gif|png|webp|css|woff2|svg|ico)$".extraConfig = ''
|
||||||
|
expires 365d;
|
||||||
|
add_header Pragma "public";
|
||||||
|
add_header Cache-Control "public";
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Deny PHP execution
|
||||||
|
locations."~ [^/]\\.php(/|$)".extraConfig = ''
|
||||||
|
deny all;
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
users.users."${domain}" = {
|
||||||
|
isNormalUser = true;
|
||||||
|
createHome = true;
|
||||||
|
home = dataDir;
|
||||||
|
homeMode = "770";
|
||||||
|
group = "nginx";
|
||||||
|
openssh.authorizedKeys.keys = [
|
||||||
|
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIErjoADQK5SJ5si/iezzwQn5xH1RkgnTIlbeE4BRU1FN"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
users.groups.${domain} = {};
|
||||||
|
}
|
||||||
@@ -1 +0,0 @@
|
|||||||
https://channels.nixos.org/nixos-23.11
|
|
||||||
@@ -1,109 +0,0 @@
|
|||||||
{ lib, pkgs, ... }: {
|
|
||||||
|
|
||||||
imports = [
|
|
||||||
./fleet.nix
|
|
||||||
./utils/bento.nix
|
|
||||||
./utils/modules/sops.nix
|
|
||||||
./utils/modules/lego/lego.nix
|
|
||||||
|
|
||||||
./utils/modules/nginx.nix
|
|
||||||
|
|
||||||
./utils/modules/autoupgrade.nix
|
|
||||||
./utils/modules/promtail
|
|
||||||
# ./utils/modules/borgbackup.nix
|
|
||||||
# ./utils/modules/netdata.nix
|
|
||||||
|
|
||||||
# fw
|
|
||||||
./modules/networking.nix
|
|
||||||
./modules/firewall.nix
|
|
||||||
# ./modules/dhcp4.nix
|
|
||||||
./modules/unbound.nix
|
|
||||||
./modules/avahi.nix
|
|
||||||
./modules/openconnect.nix
|
|
||||||
./modules/wireguard.nix
|
|
||||||
./modules/podman.nix
|
|
||||||
./modules/omada.nix
|
|
||||||
# ./modules/ddclient.nix
|
|
||||||
# ./modules/wol.nix
|
|
||||||
|
|
||||||
# microvm
|
|
||||||
./modules/microvm.nix
|
|
||||||
./modules/gitea-vm.nix
|
|
||||||
|
|
||||||
# web
|
|
||||||
./modules/web
|
|
||||||
|
|
||||||
# git
|
|
||||||
# ./modules/gitea.nix
|
|
||||||
./modules/fwmetrics.nix
|
|
||||||
|
|
||||||
# ./modules/firefox-sync.nix
|
|
||||||
|
|
||||||
# home assistant
|
|
||||||
./modules/home-assistant
|
|
||||||
# ./modules/deconz.nix
|
|
||||||
# ./modules/mopidy.nix
|
|
||||||
./modules/mosquitto.nix
|
|
||||||
./modules/snapserver.nix
|
|
||||||
|
|
||||||
# gaming
|
|
||||||
# ./modules/palworld.nix
|
|
||||||
# ./modules/ark-survival-evolved.nix
|
|
||||||
|
|
||||||
|
|
||||||
./hardware-configuration.nix
|
|
||||||
];
|
|
||||||
|
|
||||||
nixpkgs.config.permittedInsecurePackages = [
|
|
||||||
"openssl-1.1.1w"
|
|
||||||
];
|
|
||||||
|
|
||||||
nixpkgs.config.allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [
|
|
||||||
"mongodb"
|
|
||||||
];
|
|
||||||
|
|
||||||
time.timeZone = "Europe/Vienna";
|
|
||||||
|
|
||||||
sops.age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
|
|
||||||
sops.defaultSopsFile = ./secrets.yaml;
|
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; [
|
|
||||||
# bento
|
|
||||||
conntrack-tools # view network connection states
|
|
||||||
ethtool # manage NIC settings (offload, NIC feeatures, ...)
|
|
||||||
git
|
|
||||||
htop # to see the system load
|
|
||||||
tcpdump # view network traffic
|
|
||||||
vim # my preferred editor
|
|
||||||
wol
|
|
||||||
inotify-tools
|
|
||||||
];
|
|
||||||
|
|
||||||
nix.gc = {
|
|
||||||
automatic = true;
|
|
||||||
options = "--delete-older-than 60d";
|
|
||||||
};
|
|
||||||
|
|
||||||
# services.auto-cpufreq.enable = true;
|
|
||||||
# services.auto-cpufreq.settings = {
|
|
||||||
# charger = {
|
|
||||||
# governor = "powersave";
|
|
||||||
# turbo = "auto";
|
|
||||||
# };
|
|
||||||
# };
|
|
||||||
|
|
||||||
# zramSwap.enable = true;
|
|
||||||
networking.hostName = "fw-new";
|
|
||||||
services.openssh.enable = true;
|
|
||||||
users.users.root.openssh.authorizedKeys.keys = [
|
|
||||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7"
|
|
||||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIRQuPqH5fdX3KEw7DXzWEdO3AlUn1oSmtJtHB71ICoH Generated By Termius"
|
|
||||||
];
|
|
||||||
|
|
||||||
services.logind.extraConfig = "RuntimeDirectorySize=8G";
|
|
||||||
|
|
||||||
# backups
|
|
||||||
# borgbackup.repo = "u149513-sub2@u149513-sub2.your-backup.de:borg";
|
|
||||||
|
|
||||||
system.stateVersion = "23.11";
|
|
||||||
}
|
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
# Do not modify this file! It was generated by ‘nixos-generate-config’
|
|
||||||
# and may be overwritten by future invocations. Please make changes
|
|
||||||
# to /etc/nixos/configuration.nix instead.
|
|
||||||
{ config, lib, pkgs, modulesPath, ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
powerManagement.cpuFreqGovernor = lib.mkDefault "ondemand";
|
|
||||||
|
|
||||||
boot = {
|
|
||||||
loader.systemd-boot.enable = true;
|
|
||||||
loader.efi.canTouchEfiVariables = true;
|
|
||||||
|
|
||||||
kernelPackages = pkgs.linuxPackagesFor (pkgs.callPackage ./pkgs/kernel/vendor.nix {});
|
|
||||||
kernel.sysctl = {
|
|
||||||
"kernel.printk" = "1 4 1 7";
|
|
||||||
};
|
|
||||||
supportedFilesystems = lib.mkForce [ "vfat" "fat32" "exfat" "ext4" "btrfs" ];
|
|
||||||
initrd.includeDefaultModules = lib.mkForce false;
|
|
||||||
initrd.availableKernelModules = lib.mkForce [ "nvme" "mmc_block" "hid" "dm_mod" "dm_crypt" "input_leds" ];
|
|
||||||
|
|
||||||
# kernelParams copy from Armbian's /boot/armbianEnv.txt & /boot/boot.cmd
|
|
||||||
kernelParams = [
|
|
||||||
"rootwait"
|
|
||||||
|
|
||||||
"earlycon" # enable early console, so we can see the boot messages via serial port / HDMI
|
|
||||||
"consoleblank=0" # disable console blanking(screen saver)
|
|
||||||
"console=ttyS2,1500000" # serial port
|
|
||||||
"console=tty1" # HDMI
|
|
||||||
|
|
||||||
# docker optimizations
|
|
||||||
"cgroup_enable=cpuset"
|
|
||||||
"cgroup_memory=1"
|
|
||||||
"cgroup_enable=memory"
|
|
||||||
"swapaccount=1"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
hardware = {
|
|
||||||
deviceTree = {
|
|
||||||
# https://github.com/armbian/build/blob/f9d7117/config/boards/orangepi5-plus.wip#L10C51-L10C51
|
|
||||||
name = "rockchip/rk3588-orangepi-5-plus.dtb";
|
|
||||||
overlays = [
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
enableRedistributableFirmware = lib.mkForce true;
|
|
||||||
firmware = [
|
|
||||||
(pkgs.callPackage ./pkgs/orangepi-firmware {})
|
|
||||||
];
|
|
||||||
|
|
||||||
opengl.package =
|
|
||||||
(
|
|
||||||
(pkgs.mesa.override {
|
|
||||||
galliumDrivers = ["panfrost" "swrast"];
|
|
||||||
vulkanDrivers = ["swrast"];
|
|
||||||
})
|
|
||||||
.overrideAttrs (_: {
|
|
||||||
pname = "mesa-panfork";
|
|
||||||
version = "23.0.0-panfork";
|
|
||||||
src = pkgs.fetchFromGitLab {
|
|
||||||
owner = "panfork";
|
|
||||||
repo = "mesa";
|
|
||||||
rev = "120202c675749c5ef81ae4c8cdc30019b4de08f4"; # branch: csf
|
|
||||||
hash = "sha256-4eZHMiYS+sRDHNBtLZTA8ELZnLns7yT3USU5YQswxQ0=";
|
|
||||||
};
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.drivers;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
fileSystems."/" =
|
|
||||||
{ device = "/dev/disk/by-uuid/c49c99cd-9a91-485d-8572-8f83df262907";
|
|
||||||
fsType = "ext4";
|
|
||||||
};
|
|
||||||
|
|
||||||
fileSystems."/boot" =
|
|
||||||
{ device = "/dev/disk/by-uuid/12CE-A600";
|
|
||||||
fsType = "vfat";
|
|
||||||
};
|
|
||||||
|
|
||||||
swapDevices =
|
|
||||||
[ { device = "/dev/disk/by-uuid/1f3fe124-c1f6-4e3f-9e89-4aa6d87d9853"; }
|
|
||||||
];
|
|
||||||
|
|
||||||
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
|
|
||||||
# (the default) this is the recommended approach. When using systemd-networkd it's
|
|
||||||
# still possible to use this option, but it's recommended to use it in conjunction
|
|
||||||
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
|
|
||||||
networking.useDHCP = lib.mkDefault true;
|
|
||||||
# networking.interfaces.enP3p49s0.useDHCP = lib.mkDefault true;
|
|
||||||
# networking.interfaces.enP4p65s0.useDHCP = lib.mkDefault true;
|
|
||||||
# networking.interfaces.enu1u3c2.useDHCP = lib.mkDefault true;
|
|
||||||
# networking.interfaces.wlP2p33s0.useDHCP = lib.mkDefault true;
|
|
||||||
|
|
||||||
nixpkgs.hostPlatform = lib.mkDefault "aarch64-linux";
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
{ config, pkgs, ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
virtualisation.oci-containers.backend = "podman";
|
|
||||||
virtualisation.oci-containers.containers = {
|
|
||||||
ark = {
|
|
||||||
image = "hermsi/ark-server:latest";
|
|
||||||
autoStart = true;
|
|
||||||
environmentFiles = [
|
|
||||||
config.sops.secrets.ark.path
|
|
||||||
];
|
|
||||||
volumes = [
|
|
||||||
"/var/lib/ark/app:/app/"
|
|
||||||
"/var/lib/ark/backup:/home/steam/ARK-Backups"
|
|
||||||
];
|
|
||||||
extraOptions = [
|
|
||||||
"--network=server"
|
|
||||||
"--ip=10.42.97.201"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
sops.secrets.ark = {};
|
|
||||||
}
|
|
||||||
@@ -1,376 +0,0 @@
|
|||||||
{ ... }: {
|
|
||||||
services.kea.dhcp4 = {
|
|
||||||
enable = true;
|
|
||||||
settings = {
|
|
||||||
interfaces-config = {
|
|
||||||
interfaces = [
|
|
||||||
"lan"
|
|
||||||
"server"
|
|
||||||
"infrastructure"
|
|
||||||
"multimedia"
|
|
||||||
"smart"
|
|
||||||
"guest"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
lease-database = {
|
|
||||||
name = "/var/lib/kea/dhcp4.leases";
|
|
||||||
persist = true;
|
|
||||||
type = "memfile";
|
|
||||||
};
|
|
||||||
rebind-timer = 2000;
|
|
||||||
renew-timer = 1000;
|
|
||||||
subnet4 = [
|
|
||||||
{
|
|
||||||
pools = [
|
|
||||||
{
|
|
||||||
pool = "10.42.112.100 - 10.42.112.240";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
subnet = "10.42.112.0/24";
|
|
||||||
interface = "lan";
|
|
||||||
option-data = [
|
|
||||||
{
|
|
||||||
name = "routers";
|
|
||||||
data = "10.42.112.1";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "domain-name";
|
|
||||||
data = "cloonar.com";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "domain-search";
|
|
||||||
data = "cloonar.com";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "domain-name-servers";
|
|
||||||
data = "10.42.112.1";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
reservations = [
|
|
||||||
{
|
|
||||||
hw-address = "04:7c:16:d5:63:5e";
|
|
||||||
ip-address = "10.42.112.5";
|
|
||||||
server-hostname = "omada.cloonar.com";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "30:05:5c:56:62:37";
|
|
||||||
ip-address = "10.42.112.100";
|
|
||||||
server-hostname = "brn30055c566237.cloonar.com";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
pools = [
|
|
||||||
{
|
|
||||||
pool = "10.42.113.100 - 10.42.113.240";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
subnet = "10.42.113.0/24";
|
|
||||||
interface = "server";
|
|
||||||
option-data = [
|
|
||||||
{
|
|
||||||
name = "routers";
|
|
||||||
data = "10.42.113.1";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "domain-name";
|
|
||||||
data = "cloonar.com";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "domain-name-servers";
|
|
||||||
data = "10.42.113.1";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
reservations = [
|
|
||||||
{
|
|
||||||
hw-address = "1a:c4:04:6e:29:bd";
|
|
||||||
ip-address = "10.42.113.2";
|
|
||||||
server-hostname = "omada.cloonar.com";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "02:00:00:00:00:03";
|
|
||||||
ip-address = "10.42.113.5";
|
|
||||||
server-hostname = "web-02.cloonar.com";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "ea:db:d4:c1:18:ba";
|
|
||||||
ip-address = "10.42.113.50";
|
|
||||||
server-hostname = "git.cloonar.com";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "c2:4f:64:dd:13:0c";
|
|
||||||
ip-address = "10.42.113.20";
|
|
||||||
server-hostname = "home-assistant.cloonar.com";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "1a:c4:04:6e:29:02";
|
|
||||||
ip-address = "10.42.113.25";
|
|
||||||
server-hostname = "deconz.cloonar.com";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
pools = [
|
|
||||||
{
|
|
||||||
pool = "10.42.117.100 - 10.42.117.240";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
subnet = "10.42.117.0/24";
|
|
||||||
interface = "infrastructure";
|
|
||||||
option-data = [
|
|
||||||
{
|
|
||||||
name = "routers";
|
|
||||||
data = "10.42.117.1";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "domain-name";
|
|
||||||
data = "cloonar.com";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "domain-name-servers";
|
|
||||||
data = "10.42.117.1";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "capwap-ac-v4";
|
|
||||||
code = 138;
|
|
||||||
data = "10.42.117.2";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
reservations = [
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
pools = [
|
|
||||||
{
|
|
||||||
pool = "10.42.115.100 - 10.42.115.240";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
subnet = "10.42.115.0/24";
|
|
||||||
interface = "multimedia";
|
|
||||||
option-data = [
|
|
||||||
{
|
|
||||||
name = "routers";
|
|
||||||
data = "10.42.115.1";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "domain-name";
|
|
||||||
data = "cloonar.multimedia";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "domain-name-servers";
|
|
||||||
data = "10.42.115.1";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
reservations = [
|
|
||||||
{
|
|
||||||
hw-address = "c4:a7:2b:c7:ea:30";
|
|
||||||
ip-address = "10.42.115.10";
|
|
||||||
hostname = "metz.cloonar.multimedia";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "f0:2f:9e:d4:3b:21";
|
|
||||||
ip-address = "10.42.115.11";
|
|
||||||
hostname = "firetv-living";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "bc:33:29:ed:24:f0";
|
|
||||||
ip-address = "10.42.115.12";
|
|
||||||
hostname = "ps5";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "e4:2a:ac:32:3f:79";
|
|
||||||
ip-address = "10.42.115.13";
|
|
||||||
hostname = "xbox";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "98:b6:e9:b6:ef:f4";
|
|
||||||
ip-address = "10.42.115.14";
|
|
||||||
hostname = "switch";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "f0:2f:9e:c1:74:72";
|
|
||||||
ip-address = "10.42.115.21";
|
|
||||||
hostname = "firetv-bedroom";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "30:05:5c:56:62:37";
|
|
||||||
ip-address = "10.42.115.100";
|
|
||||||
server-hostname = "brn30055c566237";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
pools = [
|
|
||||||
{
|
|
||||||
pool = "10.42.127.10 - 10.42.127.254";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
subnet = "10.42.127.0/24";
|
|
||||||
interface = "guest";
|
|
||||||
option-data = [
|
|
||||||
{
|
|
||||||
name = "routers";
|
|
||||||
data = "10.42.127.1";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "domain-name-servers";
|
|
||||||
data = "9.9.9.9";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
pools = [
|
|
||||||
{
|
|
||||||
pool = "10.42.116.100 - 10.42.116.240";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
subnet = "10.42.116.0/24";
|
|
||||||
interface = "smart";
|
|
||||||
option-data = [
|
|
||||||
{
|
|
||||||
name = "routers";
|
|
||||||
data = "10.42.116.1";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "domain-name";
|
|
||||||
data = "cloonar.smart";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "domain-name-servers";
|
|
||||||
data = "10.42.116.1";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
reservations = [
|
|
||||||
# need fixed ips for all shelly devices
|
|
||||||
# living room 1 - 14
|
|
||||||
# 10.42.100.2 # bulb1
|
|
||||||
# 10.42.100.3 # bulb2
|
|
||||||
# 10.42.100.4 # bulb3
|
|
||||||
# 10.42.100.5 # bulb4
|
|
||||||
# 10.42.100.6 # bulb5
|
|
||||||
# 10.42.100.7 # bulb6
|
|
||||||
# 10.42.100.8 # piano
|
|
||||||
# 10.42.100.9 # switch
|
|
||||||
# 10.42.100.10 # steamdeck
|
|
||||||
# kitchen:
|
|
||||||
# 10.42.100.17 # coffee
|
|
||||||
# 10.42.100.18 # bar
|
|
||||||
# bedroom:
|
|
||||||
# 10.42.100.33 # switch
|
|
||||||
# 10.42.100.34 # button1
|
|
||||||
# 10.42.100.35 # button2
|
|
||||||
# 10.42.100.36 # readingled1
|
|
||||||
# 10.42.100.37 # readingled2
|
|
||||||
# 10.42.100.38 # bedled
|
|
||||||
# bath:
|
|
||||||
# 10.42.100.49 # switch
|
|
||||||
# 10.42.100.50 # bulb1
|
|
||||||
# 10.42.100.51 # bulb2
|
|
||||||
# 10.42.100.52 # smallswitch
|
|
||||||
# 10.42.100.53 # ht
|
|
||||||
# hallway:
|
|
||||||
# 10.42.100.65 # switch
|
|
||||||
# 10.42.100.66 # bulb1
|
|
||||||
# 10.42.100.67 # bulb2
|
|
||||||
# 10.42.100.68 # bulb3
|
|
||||||
# 10.42.100.69 # bulb4
|
|
||||||
# toilet:
|
|
||||||
# 10.42.100.81 # switch
|
|
||||||
# 10.42.100.82 # bulb
|
|
||||||
# storage:
|
|
||||||
# 10.42.100.97 # switch
|
|
||||||
|
|
||||||
{
|
|
||||||
hw-address = "60:a4:23:97:4a:ec";
|
|
||||||
ip-address = "10.42.116.21";
|
|
||||||
server-hostname = "shellymotionsensor-60A423974AEC";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "8c:aa:b5:61:6f:e2";
|
|
||||||
ip-address = "10.42.116.103";
|
|
||||||
server-hostname = "ShellyBulbDuo-8CAAB5616FE2";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "8c:aa:b5:61:6e:9e";
|
|
||||||
ip-address = "10.42.116.104";
|
|
||||||
server-hostname = "ShellyBulbDuo-8CAAB5616E9E";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "cc:50:e3:bc:27:64";
|
|
||||||
ip-address = "10.42.116.112";
|
|
||||||
server-hostname = "Nuki_Bridge_1A753F72";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "e8:db:84:a9:ea:be";
|
|
||||||
ip-address = "10.42.116.117";
|
|
||||||
server-hostname = "ShellyBulbDuo-E8DB84A9EABE";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "e8:db:84:a9:d1:8b";
|
|
||||||
ip-address = "10.42.116.119";
|
|
||||||
server-hostname = "shellycolorbulb-E8DB84A9D18B";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "3c:61:05:e5:96:e0";
|
|
||||||
ip-address = "10.42.116.120";
|
|
||||||
server-hostname = "shellycolorbulb-3C6105E596E0";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "e8:db:84:a9:d7:ef";
|
|
||||||
ip-address = "10.42.116.121";
|
|
||||||
server-hostname = "shellycolorbulb-E8DB84A9D7EF";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "e8:db:84:aa:51:aa";
|
|
||||||
ip-address = "10.42.116.122";
|
|
||||||
server-hostname = "shellycolorbulb-E8DB84AA51AA";
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
hw-address = "34:94:54:79:bc:57";
|
|
||||||
ip-address = "10.42.116.130";
|
|
||||||
server-hostname = "shellycolorbulb-34945479bc57";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "48:55:19:d9:a1:b2";
|
|
||||||
ip-address = "10.42.116.131";
|
|
||||||
server-hostname = "shellycolorbulb-485519d9a1b2";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "48:55:19:d9:ae:95";
|
|
||||||
ip-address = "10.42.116.132";
|
|
||||||
server-hostname = "shellycolorbulb-485519d9ae95";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "48:55:19:d9:4a:28";
|
|
||||||
ip-address = "10.42.116.133";
|
|
||||||
server-hostname = "shellycolorbulb-485519d94a28";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "48:55:19:da:6b:6a";
|
|
||||||
ip-address = "10.42.116.134";
|
|
||||||
server-hostname = "shellycolorbulb-485519da6b6a";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "48:55:19:d9:e0:18";
|
|
||||||
ip-address = "10.42.116.135";
|
|
||||||
server-hostname = "shellycolorbulb-485519d9e018";
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
hw-address = "34:6f:24:f3:af:ad";
|
|
||||||
ip-address = "10.42.116.137";
|
|
||||||
server-hostname = "daikin86604";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "34:6f:24:c1:f8:54";
|
|
||||||
ip-address = "10.42.116.139";
|
|
||||||
server-hostname = "daikin53800";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
valid-lifetime = 4000;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
{ config, pkgs, ... }:
|
|
||||||
let
|
|
||||||
domain = "sync.cloonar.com";
|
|
||||||
in {
|
|
||||||
sops.secrets.firefox-sync = { };
|
|
||||||
|
|
||||||
security.acme.certs."${domain}" = {
|
|
||||||
group = "nginx";
|
|
||||||
};
|
|
||||||
|
|
||||||
containers."firefox-sync" = {
|
|
||||||
autoStart = true;
|
|
||||||
ephemeral = false; # because of ssh key
|
|
||||||
privateNetwork = true;
|
|
||||||
hostBridge = "server";
|
|
||||||
hostAddress = "10.42.97.1";
|
|
||||||
localAddress = "10.42.97.51/24";
|
|
||||||
bindMounts = {
|
|
||||||
"/run/secrets/firefox-sync" = {
|
|
||||||
hostPath = "/run/secrets/firefox-sync";
|
|
||||||
isReadOnly = true;
|
|
||||||
};
|
|
||||||
"/var/lib/acme/${domain}/" = {
|
|
||||||
hostPath = "${config.security.acme.certs.${domain}.directory}";
|
|
||||||
isReadOnly = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
config = { lib, config, pkgs, ... }: {
|
|
||||||
networking = {
|
|
||||||
hostName = "firefox-sync";
|
|
||||||
useHostResolvConf = false;
|
|
||||||
defaultGateway = {
|
|
||||||
address = "10.42.97.1";
|
|
||||||
interface = "eth0";
|
|
||||||
};
|
|
||||||
firewall.enable = false;
|
|
||||||
nameservers = [ "10.42.97.1" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
services.nginx.enable = true;
|
|
||||||
services.nginx.virtualHosts."${domain}" = {
|
|
||||||
sslCertificate = "/var/lib/acme/${domain}/fullchain.pem";
|
|
||||||
sslCertificateKey = "/var/lib/acme/${domain}/key.pem";
|
|
||||||
sslTrustedCertificate = "/var/lib/acme/${domain}/chain.pem";
|
|
||||||
listen = [
|
|
||||||
{
|
|
||||||
addr = "0.0.0.0";
|
|
||||||
ssl = true;
|
|
||||||
port = 5000;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
locations."/" = {
|
|
||||||
proxyPass = "http://localhost:5001/";
|
|
||||||
recommendedProxySettings = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
services.mysql.package = pkgs.mariadb;
|
|
||||||
services.firefox-syncserver = {
|
|
||||||
enable = true;
|
|
||||||
singleNode = {
|
|
||||||
enable = true;
|
|
||||||
enableNginx = false;
|
|
||||||
hostname = domain;
|
|
||||||
};
|
|
||||||
settings = {
|
|
||||||
port = 5001;
|
|
||||||
tokenserver.enable = true;
|
|
||||||
};
|
|
||||||
secrets = "/run/secrets/firefox-sync";
|
|
||||||
logLevel = "trace";
|
|
||||||
};
|
|
||||||
|
|
||||||
services.openssh.enable = true;
|
|
||||||
users.users.root.openssh.authorizedKeys.keys = [
|
|
||||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7"
|
|
||||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIRQuPqH5fdX3KEw7DXzWEdO3AlUn1oSmtJtHB71ICoH Generated By Termius"
|
|
||||||
];
|
|
||||||
|
|
||||||
system.stateVersion = "23.05";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,160 +0,0 @@
|
|||||||
{ pkgs, ... }: {
|
|
||||||
networking = {
|
|
||||||
firewall.checkReversePath = false;
|
|
||||||
nat.enable = false;
|
|
||||||
nftables = {
|
|
||||||
enable = true;
|
|
||||||
tables = {
|
|
||||||
"cloonar-fw" = {
|
|
||||||
family = "inet";
|
|
||||||
content = ''
|
|
||||||
chain output {
|
|
||||||
type filter hook output priority 100; policy accept;
|
|
||||||
}
|
|
||||||
|
|
||||||
chain rpfilter {
|
|
||||||
type filter hook prerouting priority mangle + 10; policy drop;
|
|
||||||
meta nfproto ipv4 udp sport . udp dport { 68 . 67, 67 . 68 } accept comment "DHCPv4 client/server"
|
|
||||||
fib saddr . mark . iif oif exists accept
|
|
||||||
}
|
|
||||||
|
|
||||||
chain input {
|
|
||||||
type filter hook input priority filter; policy drop;
|
|
||||||
iifname "lo" accept comment "trusted interfaces"
|
|
||||||
iifname "lan" counter accept comment "Spice"
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
chain input-allow {
|
|
||||||
udp dport != { 53, 5353 } ct state new limit rate over 1/second burst 10 packets drop comment "rate limit for new connections"
|
|
||||||
iifname lo accept
|
|
||||||
iifname "wan" udp dport 51820 counter accept comment "Wireguard traffic"
|
|
||||||
iifname "wan" tcp dport 9273 counter accept comment "Prometheus traffic"
|
|
||||||
iifname "lan" tcp dport 5931 counter accept comment "Spice"
|
|
||||||
iifname { "wan", "server", "vserver", "vm-*", "lan", "wg_cloonar" } counter accept comment "allow trusted to router"
|
|
||||||
iifname { "multimedia", "smart", "infrastructure", "podman0" } udp dport { 53, 5353 } counter accept comment "DNS"
|
|
||||||
iifname { "wan", "multimedia" } icmp type { echo-request, destination-unreachable, time-exceeded } counter accept comment "Allow select ICMP"
|
|
||||||
|
|
||||||
# Accept mDNS for avahi reflection
|
|
||||||
iifname "server" ip saddr 10.42.113.20/32 tcp dport { llmnr } counter accept
|
|
||||||
iifname "server" ip saddr 10.42.113.20/32 udp dport { mdns, llmnr } counter accept
|
|
||||||
|
|
||||||
# Allow all returning traffic
|
|
||||||
ct state { established, related } counter accept
|
|
||||||
|
|
||||||
# Allow returning traffic from wrwks and drop everthing else
|
|
||||||
iifname "wrwks" ct state { established, related } counter accept
|
|
||||||
iifname "wrwks" drop
|
|
||||||
|
|
||||||
# Allow returning traffic from wg_epicenter and drop everthing else
|
|
||||||
iifname "wg_epicenter" ct state { established, related } counter accept
|
|
||||||
iifname "wg_epicenter" drop
|
|
||||||
|
|
||||||
# Allow returning traffic from wg_ghetto_at and drop everthing else
|
|
||||||
iifname "wg_ghetto_at" ct state { established, related } counter accept
|
|
||||||
iifname "wg_ghetto_at" drop
|
|
||||||
|
|
||||||
# Allow returning traffic from wan and drop everthing else
|
|
||||||
iifname "wan" ct state { established, related } accept comment "Allow established traffic"
|
|
||||||
iifname "wan" icmp type { echo-request, destination-unreachable, time-exceeded } counter accept comment "Allow select ICMP"
|
|
||||||
iifname "wan" counter drop comment "Drop all other unsolicited traffic from wan"
|
|
||||||
|
|
||||||
limit rate 60/minute burst 100 packets log prefix "Input - Drop: " comment "Log any unmatched traffic"
|
|
||||||
}
|
|
||||||
|
|
||||||
chain forward {
|
|
||||||
type filter hook forward priority filter; policy drop;
|
|
||||||
|
|
||||||
iifname "wg_cloonar" counter accept comment "test wireguard"
|
|
||||||
|
|
||||||
iifname "wg_cloonar" oifname lo counter accept comment "wireguard to server"
|
|
||||||
|
|
||||||
# enable flow offloading for better throughput
|
|
||||||
# ip protocol { tcp, udp } flow offload @f
|
|
||||||
|
|
||||||
# broadcast
|
|
||||||
iifname "server" oifname { "lan", "multimedia" } udp dport { 9 } counter accept comment "wakeonlan"
|
|
||||||
|
|
||||||
# multimedia airplay
|
|
||||||
iifname "multimedia" oifname { "lan" } counter accept
|
|
||||||
iifname "multimedia" oifname "server" tcp dport { 1704, 1705 } counter accept
|
|
||||||
iifname "lan" oifname "server" udp dport { 5000, 5353, 6001 - 6011 } counter accept
|
|
||||||
# avahi
|
|
||||||
iifname "server" ip saddr 10.42.113.20/32 oifname { "lan" } counter accept
|
|
||||||
|
|
||||||
# smart home coap
|
|
||||||
iifname "smart" oifname "server" ip daddr 10.42.113.20/32 udp dport { 5683 } counter accept
|
|
||||||
iifname "smart" oifname "server" ip daddr 10.42.113.20/32 tcp dport { 1883 } counter accept
|
|
||||||
|
|
||||||
# Forward to git server
|
|
||||||
oifname "server" ip daddr 10.42.113.50 tcp dport { 22 } counter accept
|
|
||||||
oifname "server" ip daddr 10.42.113.5 tcp dport { 80, 443 } counter accept
|
|
||||||
|
|
||||||
# lan and vpn to any
|
|
||||||
# TODO: disable wan when finished
|
|
||||||
iifname { "lan", "server", "vserver", "wg_cloonar" } oifname { "lan", "vb-*", "vm-*", "server", "vserver", "infrastructure", "multimedia", "smart", "wg_cloonar" } counter log prefix "basic forward allow rule" accept
|
|
||||||
iifname { "lan", "server", "wg_cloonar" } oifname { "wrwks", "wg_epicenter", "wg_ghetto_at" } counter accept
|
|
||||||
iifname { "infrastructure" } oifname { "server", "vserver" } counter accept
|
|
||||||
iifname { "lan", "wan" } udp dport { 8211, 27015 } counter accept comment "palworld"
|
|
||||||
|
|
||||||
# accept palword server
|
|
||||||
iifname { "wan", "lan" } oifname "podman0" udp dport { 8211, 27015 } counter accept comment "palworld"
|
|
||||||
# forward to ark server
|
|
||||||
oifname "server" ip daddr 10.42.113.201 tcp dport { 27020 } counter accept comment "ark survival evolved"
|
|
||||||
oifname "server" ip daddr 10.42.113.201 udp dport { 7777, 7778, 27015 } counter accept comment "ark survival evolved"
|
|
||||||
|
|
||||||
# firefox-sync
|
|
||||||
oifname "server" ip daddr 10.42.113.51 tcp dport { 5000 } counter accept comment "firefox-sync"
|
|
||||||
|
|
||||||
# allow all established, related
|
|
||||||
ct state { established, related } accept comment "Allow established traffic"
|
|
||||||
|
|
||||||
# Allow trusted network WAN access
|
|
||||||
iifname {
|
|
||||||
"lan",
|
|
||||||
"infrastructure",
|
|
||||||
"server",
|
|
||||||
"vserver",
|
|
||||||
"multimedia",
|
|
||||||
"smart",
|
|
||||||
"wg_cloonar",
|
|
||||||
"podman*",
|
|
||||||
"guest",
|
|
||||||
"vb-*",
|
|
||||||
"vm-*",
|
|
||||||
} oifname {
|
|
||||||
"wan",
|
|
||||||
} counter accept comment "Allow trusted LAN to WAN"
|
|
||||||
|
|
||||||
limit rate 60/minute burst 100 packets log prefix "Forward - Drop: " comment "Log any unmatched traffic"
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
"cloonar-nat" = {
|
|
||||||
family = "ip";
|
|
||||||
content = ''
|
|
||||||
chain prerouting {
|
|
||||||
type nat hook prerouting priority filter; policy accept;
|
|
||||||
iifname "server" ip daddr 10.42.96.255 udp dport { 9 } dnat to 10.42.96.255
|
|
||||||
# iifname "wan" tcp dport { 22 } dnat to 10.42.113.50
|
|
||||||
iifname "wan" tcp dport { 80, 443 } dnat to 10.42.113.5
|
|
||||||
iifname "wan" tcp dport { 5000 } dnat to 10.42.113.51
|
|
||||||
iifname { "wan", "lan" } udp dport { 7777, 7778, 27015 } dnat to 10.42.113.201
|
|
||||||
iifname { "wan", "lan" } tcp dport { 27020 } dnat to 10.42.113.201
|
|
||||||
}
|
|
||||||
|
|
||||||
# Setup NAT masquerading on external interfaces
|
|
||||||
chain postrouting {
|
|
||||||
type nat hook postrouting priority filter; policy accept;
|
|
||||||
oifname { "wan", "wg_cloonar", "wrwks", "wg_epicenter", "wg_ghetto_at" } masquerade
|
|
||||||
iifname { "wan", "wg_cloonar" } ip daddr 10.42.113.50 masquerade
|
|
||||||
iifname { "wan", "wg_cloonar" } ip daddr 10.42.113.51 masquerade
|
|
||||||
iifname { "wan", "wg_cloonar" } ip daddr 10.42.113.201 masquerade
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,175 +0,0 @@
|
|||||||
{ config, nixpkgs, pkgs, ... }: let
|
|
||||||
hostname = "git";
|
|
||||||
json = pkgs.formats.json { };
|
|
||||||
pkgs-with-gitea = import (builtins.fetchGit {
|
|
||||||
name = "new-gitea";
|
|
||||||
url = "https://github.com/nixos/nixpkgs/";
|
|
||||||
rev = "159be5db480d1df880a0135ca0bfed84c2f88353";
|
|
||||||
}) {};
|
|
||||||
in {
|
|
||||||
microvm.vms = {
|
|
||||||
gitea = {
|
|
||||||
config = {
|
|
||||||
microvm = {
|
|
||||||
hypervisor = "cloud-hypervisor";
|
|
||||||
shares = [
|
|
||||||
{
|
|
||||||
source = "/nix/store";
|
|
||||||
mountPoint = "/nix/.ro-store";
|
|
||||||
tag = "ro-store";
|
|
||||||
proto = "virtiofs";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
source = "/var/lib/acme/git.cloonar.com";
|
|
||||||
mountPoint = "/var/lib/acme/${hostname}.cloonar.com";
|
|
||||||
tag = "ro-cert";
|
|
||||||
proto = "virtiofs";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
interfaces = [
|
|
||||||
{
|
|
||||||
type = "tap";
|
|
||||||
id = "vm-${hostname}";
|
|
||||||
mac = "02:00:00:00:00:01";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
imports = [
|
|
||||||
../fleet.nix
|
|
||||||
];
|
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; [
|
|
||||||
vim # my preferred editor
|
|
||||||
];
|
|
||||||
|
|
||||||
networking = {
|
|
||||||
hostName = hostname;
|
|
||||||
firewall = {
|
|
||||||
enable = true;
|
|
||||||
allowedTCPPorts = [ 22 80 443 ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
services.nginx.enable = true;
|
|
||||||
services.nginx.virtualHosts."${hostname}.cloonar.com" = {
|
|
||||||
sslCertificate = "/var/lib/acme/${hostname}.cloonar.com/fullchain.pem";
|
|
||||||
sslCertificateKey = "/var/lib/acme/${hostname}.cloonar.com/key.pem";
|
|
||||||
sslTrustedCertificate = "/var/lib/acme/${hostname}.cloonar.com/chain.pem";
|
|
||||||
forceSSL = true;
|
|
||||||
locations."/" = {
|
|
||||||
proxyPass = "http://localhost:3001/";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
services.gitea = {
|
|
||||||
enable = true;
|
|
||||||
package = pkgs-with-gitea.gitea;
|
|
||||||
appName = "Cloonar Gitea server"; # Give the site a name
|
|
||||||
settings = {
|
|
||||||
server = {
|
|
||||||
ROOT_URL = "https://${hostname}.cloonar.com/";
|
|
||||||
HTTP_PORT = 3001;
|
|
||||||
DOMAIN = "${hostname}.cloonar.com";
|
|
||||||
};
|
|
||||||
openid = {
|
|
||||||
ENABLE_OPENID_SIGNIN = true;
|
|
||||||
ENABLE_OPENID_SIGNUP = true;
|
|
||||||
WHITELISTED_URIS = "auth.cloonar.com";
|
|
||||||
};
|
|
||||||
service = {
|
|
||||||
DISABLE_REGISTRATION = true;
|
|
||||||
ALLOW_ONLY_EXTERNAL_REGISTRATION = true;
|
|
||||||
SHOW_REGISTRATION_BUTTON = false;
|
|
||||||
};
|
|
||||||
actions.ENABLED=true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
services.openssh.enable = true;
|
|
||||||
users.users.root.openssh.authorizedKeys.keys = [
|
|
||||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7"
|
|
||||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIRQuPqH5fdX3KEw7DXzWEdO3AlUn1oSmtJtHB71ICoH Generated By Termius"
|
|
||||||
];
|
|
||||||
|
|
||||||
system.stateVersion = "22.05";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
gitea-runner = {
|
|
||||||
config = {
|
|
||||||
microvm = {
|
|
||||||
mem = 12288;
|
|
||||||
shares = [
|
|
||||||
{
|
|
||||||
source = "/nix/store";
|
|
||||||
mountPoint = "/nix/.ro-store";
|
|
||||||
tag = "ro-store";
|
|
||||||
proto = "virtiofs";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
source = "/run/secrets";
|
|
||||||
mountPoint = "/run/secrets";
|
|
||||||
tag = "ro-token";
|
|
||||||
proto = "virtiofs";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
volumes = [
|
|
||||||
{
|
|
||||||
image = "rootfs.img";
|
|
||||||
mountPoint = "/";
|
|
||||||
size = 102400;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
interfaces = [
|
|
||||||
{
|
|
||||||
type = "tap";
|
|
||||||
id = "vm-gitea-runner";
|
|
||||||
mac = "02:00:00:00:00:02";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; [
|
|
||||||
vim # my preferred editor
|
|
||||||
];
|
|
||||||
|
|
||||||
networking.hostName = "gitea-runner";
|
|
||||||
|
|
||||||
virtualisation.podman.enable = true;
|
|
||||||
|
|
||||||
services.gitea-actions-runner.instances.vm = {
|
|
||||||
enable = true;
|
|
||||||
url = "https://git.cloonar.com";
|
|
||||||
name = "vm";
|
|
||||||
tokenFile = "/run/secrets/gitea-runner-token";
|
|
||||||
labels = [
|
|
||||||
"ubuntu-latest:docker://shivammathur/node:latest"
|
|
||||||
];
|
|
||||||
settings = {
|
|
||||||
container = {
|
|
||||||
network = "podman";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
services.openssh.enable = true;
|
|
||||||
users.users.root.openssh.authorizedKeys.keys = [
|
|
||||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7"
|
|
||||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIRQuPqH5fdX3KEw7DXzWEdO3AlUn1oSmtJtHB71ICoH Generated By Termius"
|
|
||||||
];
|
|
||||||
|
|
||||||
system.stateVersion = "22.05";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
sops.secrets.gitea-runner-token = {};
|
|
||||||
|
|
||||||
environment = {
|
|
||||||
systemPackages = [
|
|
||||||
pkgs.qemu
|
|
||||||
pkgs.quickemu
|
|
||||||
];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,110 +0,0 @@
|
|||||||
{ config, pkgs, ... }:
|
|
||||||
let
|
|
||||||
cids = import ../modules/staticids.nix;
|
|
||||||
domain = "git.cloonar.com";
|
|
||||||
|
|
||||||
user = {
|
|
||||||
isSystemUser = true;
|
|
||||||
uid = cids.uids.gitea;
|
|
||||||
group = "gitea";
|
|
||||||
home = "/var/lib/gitea";
|
|
||||||
createHome = true;
|
|
||||||
};
|
|
||||||
group = {
|
|
||||||
gid = cids.gids.gitea;
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
users.users.gitea = user;
|
|
||||||
users.groups.gitea = group;
|
|
||||||
|
|
||||||
security.acme.certs."${domain}" = {
|
|
||||||
group = "nginx";
|
|
||||||
};
|
|
||||||
|
|
||||||
containers.git = {
|
|
||||||
autoStart = true;
|
|
||||||
ephemeral = false; # because of ssh key
|
|
||||||
privateNetwork = true;
|
|
||||||
hostBridge = "server";
|
|
||||||
hostAddress = "10.42.97.1";
|
|
||||||
localAddress = "10.42.97.50/24";
|
|
||||||
bindMounts = {
|
|
||||||
"/var/lib/gitea" = {
|
|
||||||
hostPath = "/var/lib/gitea/";
|
|
||||||
isReadOnly = false;
|
|
||||||
};
|
|
||||||
"/var/lib/acme/gitea/" = {
|
|
||||||
hostPath = "${config.security.acme.certs.${domain}.directory}";
|
|
||||||
isReadOnly = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
config = { lib, config, pkgs, ... }: {
|
|
||||||
imports = [
|
|
||||||
../fleet.nix
|
|
||||||
];
|
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; [
|
|
||||||
vim # my preferred editor
|
|
||||||
];
|
|
||||||
|
|
||||||
networking = {
|
|
||||||
hostName = "git";
|
|
||||||
useHostResolvConf = false;
|
|
||||||
defaultGateway = {
|
|
||||||
address = "10.42.96.1";
|
|
||||||
interface = "eth0";
|
|
||||||
};
|
|
||||||
firewall.enable = false;
|
|
||||||
nameservers = [ "10.42.97.1" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
services.nginx.enable = true;
|
|
||||||
services.nginx.virtualHosts."${domain}" = {
|
|
||||||
sslCertificate = "/var/lib/acme/gitea/fullchain.pem";
|
|
||||||
sslCertificateKey = "/var/lib/acme/gitea/key.pem";
|
|
||||||
sslTrustedCertificate = "/var/lib/acme/gitea/chain.pem";
|
|
||||||
forceSSL = true;
|
|
||||||
locations."/" = {
|
|
||||||
proxyPass = "http://localhost:3001/";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
services.gitea = {
|
|
||||||
enable = true;
|
|
||||||
appName = "Cloonar Gitea server"; # Give the site a name
|
|
||||||
settings = {
|
|
||||||
server = {
|
|
||||||
ROOT_URL = "https://${domain}/";
|
|
||||||
HTTP_PORT = 3001;
|
|
||||||
DOMAIN = domain;
|
|
||||||
};
|
|
||||||
openid = {
|
|
||||||
ENABLE_OPENID_SIGNIN = false;
|
|
||||||
ENABLE_OPENID_SIGNUP = true;
|
|
||||||
WHITELISTED_URIS = "auth.cloonar.com";
|
|
||||||
};
|
|
||||||
service = {
|
|
||||||
DISABLE_REGISTRATION = false;
|
|
||||||
ALLOW_ONLY_EXTERNAL_REGISTRATION = true;
|
|
||||||
SHOW_REGISTRATION_BUTTON = false;
|
|
||||||
};
|
|
||||||
actions.ENABLED=true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
services.openssh.enable = true;
|
|
||||||
users.users.root.openssh.authorizedKeys.keys = [
|
|
||||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7"
|
|
||||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIRQuPqH5fdX3KEw7DXzWEdO3AlUn1oSmtJtHB71ICoH Generated By Termius"
|
|
||||||
];
|
|
||||||
|
|
||||||
users.users.gitea = user;
|
|
||||||
users.groups.gitea = group;
|
|
||||||
|
|
||||||
system.stateVersion = "23.05";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
sops.secrets.gitea-runner = {};
|
|
||||||
}
|
|
||||||
@@ -1,254 +0,0 @@
|
|||||||
{ config, pkgs, ... }:
|
|
||||||
let
|
|
||||||
domain = "home-assistant.cloonar.com";
|
|
||||||
release2405 = import <nixos-24.05> { config = config.nixpkgs.config; };
|
|
||||||
pkgs-with-home-assistant = import (builtins.fetchGit {
|
|
||||||
name = "new-home-assistant";
|
|
||||||
url = "https://github.com/nixos/nixpkgs/";
|
|
||||||
rev = "268bb5090a3c6ac5e1615b38542a868b52ef8088";
|
|
||||||
}) {};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
users.users.hass = {
|
|
||||||
home = "/var/lib/hass";
|
|
||||||
createHome = true;
|
|
||||||
group = "hass";
|
|
||||||
uid = config.ids.uids.hass;
|
|
||||||
extraGroups = [ "dialout" ];
|
|
||||||
};
|
|
||||||
users.groups.hass.gid = config.ids.gids.hass;
|
|
||||||
|
|
||||||
security.acme.certs."${domain}" = {
|
|
||||||
group = "nginx";
|
|
||||||
};
|
|
||||||
|
|
||||||
sops.secrets."home-assistant-secrets.yaml" = {
|
|
||||||
owner = "hass";
|
|
||||||
restartUnits = [ "container@hass.service" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
sops.secrets."home-assistant-ldap" = {
|
|
||||||
owner = "hass";
|
|
||||||
};
|
|
||||||
|
|
||||||
containers.hass = {
|
|
||||||
autoStart = true;
|
|
||||||
ephemeral = false;
|
|
||||||
privateNetwork = true;
|
|
||||||
hostBridge = "server";
|
|
||||||
hostAddress = "10.42.113.1";
|
|
||||||
localAddress = "10.42.113.20/24";
|
|
||||||
extraFlags = [
|
|
||||||
"--capability=CAP_NET_ADMIN"
|
|
||||||
];
|
|
||||||
# allowedDevices = [
|
|
||||||
# {
|
|
||||||
# modifier = "rwm";
|
|
||||||
# node = "char-usb_device";
|
|
||||||
# }
|
|
||||||
# {
|
|
||||||
# modifier = "rwm";
|
|
||||||
# node = "char-ttyUSB";
|
|
||||||
# }
|
|
||||||
# ];
|
|
||||||
bindMounts = {
|
|
||||||
# "/dev/ttyUSB0" = {
|
|
||||||
# hostPath = "/dev/ttyUSB0";
|
|
||||||
# isReadOnly = false;
|
|
||||||
# };
|
|
||||||
"/etc/localtime" = {
|
|
||||||
hostPath = "/etc/localtime";
|
|
||||||
};
|
|
||||||
"/var/lib/hass" = {
|
|
||||||
hostPath = "/var/lib/hass/";
|
|
||||||
isReadOnly = false;
|
|
||||||
};
|
|
||||||
"/var/lib/acme/hass/" = {
|
|
||||||
hostPath = "${config.security.acme.certs.${domain}.directory}";
|
|
||||||
};
|
|
||||||
"/run/secrets/home-assistant-ldap" = {
|
|
||||||
hostPath = config.sops.secrets."home-assistant-ldap".path;
|
|
||||||
};
|
|
||||||
"/var/lib/hass/secrets.yaml" = {
|
|
||||||
hostPath = config.sops.secrets."home-assistant-secrets.yaml".path;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
config = { lib, config, pkgs, ... }: {
|
|
||||||
imports = [
|
|
||||||
./3dprinter.nix
|
|
||||||
./ac.nix
|
|
||||||
# ./aeg.nix
|
|
||||||
./battery.nix
|
|
||||||
./electricity.nix
|
|
||||||
./enocean.nix
|
|
||||||
./ldap.nix
|
|
||||||
./light.nix
|
|
||||||
./locks.nix
|
|
||||||
./multimedia.nix
|
|
||||||
./music.nix
|
|
||||||
./notify.nix
|
|
||||||
./pc.nix
|
|
||||||
./pushover.nix
|
|
||||||
./presense.nix
|
|
||||||
./roborock.nix
|
|
||||||
./scene-switch.nix
|
|
||||||
./shelly.nix
|
|
||||||
./sleep.nix
|
|
||||||
./snapcast.nix
|
|
||||||
];
|
|
||||||
|
|
||||||
networking = {
|
|
||||||
hostName = "home-assistant";
|
|
||||||
useHostResolvConf = false;
|
|
||||||
defaultGateway = {
|
|
||||||
address = "10.42.96.1";
|
|
||||||
interface = "eth0";
|
|
||||||
};
|
|
||||||
firewall.enable = false;
|
|
||||||
nameservers = [ "10.42.97.1" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
environment.systemPackages = [
|
|
||||||
pkgs.wol
|
|
||||||
pkgs.mariadb
|
|
||||||
];
|
|
||||||
|
|
||||||
services.nginx.enable = true;
|
|
||||||
services.nginx.virtualHosts."${domain}" = {
|
|
||||||
sslCertificate = "/var/lib/acme/hass/fullchain.pem";
|
|
||||||
sslCertificateKey = "/var/lib/acme/hass/key.pem";
|
|
||||||
sslTrustedCertificate = "/var/lib/acme/hass/chain.pem";
|
|
||||||
forceSSL = true;
|
|
||||||
extraConfig = ''
|
|
||||||
proxy_buffering off;
|
|
||||||
'';
|
|
||||||
locations."/".extraConfig = ''
|
|
||||||
proxy_pass http://127.0.0.1:8123;
|
|
||||||
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;
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
services.home-assistant = {
|
|
||||||
package = pkgs-with-home-assistant.home-assistant;
|
|
||||||
enable = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
services.home-assistant.extraComponents = [
|
|
||||||
"mobile_app"
|
|
||||||
"backup"
|
|
||||||
"denonavr"
|
|
||||||
"androidtv"
|
|
||||||
"rainbird"
|
|
||||||
"zha"
|
|
||||||
"tplink_omada"
|
|
||||||
];
|
|
||||||
|
|
||||||
services.mysql = {
|
|
||||||
enable = true;
|
|
||||||
package = pkgs.mariadb;
|
|
||||||
ensureDatabases = [ "hass" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
services.mysqlBackup = {
|
|
||||||
enable = true;
|
|
||||||
databases = [ "hass" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
services.home-assistant.config =
|
|
||||||
let
|
|
||||||
hiddenEntities = [
|
|
||||||
"sensor.last_boot"
|
|
||||||
"sensor.date"
|
|
||||||
];
|
|
||||||
in
|
|
||||||
{
|
|
||||||
recorder = {
|
|
||||||
db_url = "mysql://hass@localhost/hass?unix_socket=/var/run/mysqld/mysqld.sock";
|
|
||||||
};
|
|
||||||
homeassistant = {
|
|
||||||
name = "Home";
|
|
||||||
latitude = "!secret home_latitude";
|
|
||||||
longitude = "!secret home_longitude";
|
|
||||||
elevation = "!secret home_elevation";
|
|
||||||
unit_system = "metric";
|
|
||||||
currency = "EUR";
|
|
||||||
country = "AT";
|
|
||||||
time_zone = "Europe/Vienna";
|
|
||||||
external_url = "https://${domain}";
|
|
||||||
};
|
|
||||||
zone = {
|
|
||||||
name = "Home";
|
|
||||||
latitude = "!secret home_latitude";
|
|
||||||
longitude = "!secret home_longitude";
|
|
||||||
radius = 35;
|
|
||||||
icon = "mdi:account-multiple";
|
|
||||||
|
|
||||||
};
|
|
||||||
automation = "!include automations.yaml";
|
|
||||||
frontend = { };
|
|
||||||
http = {
|
|
||||||
use_x_forwarded_for = true;
|
|
||||||
trusted_proxies = [
|
|
||||||
"127.0.0.1"
|
|
||||||
"::1"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
api = { };
|
|
||||||
history.exclude = {
|
|
||||||
entities = hiddenEntities;
|
|
||||||
domains = [
|
|
||||||
"automation"
|
|
||||||
"updater"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
"map" = { };
|
|
||||||
enocean = {
|
|
||||||
device = "/dev/ttyUSB0";
|
|
||||||
};
|
|
||||||
# logbook.exclude.entities = "hiddenEntities";
|
|
||||||
logger = {
|
|
||||||
default = "info";
|
|
||||||
};
|
|
||||||
|
|
||||||
#icloud = {
|
|
||||||
# username = "!secret icloud_email";
|
|
||||||
# password = "!secret icloud_password";
|
|
||||||
# with_family = true;
|
|
||||||
#};
|
|
||||||
network = { };
|
|
||||||
zeroconf = { };
|
|
||||||
system_health = { };
|
|
||||||
default_config = { };
|
|
||||||
system_log = { };
|
|
||||||
sensor = [
|
|
||||||
{
|
|
||||||
platform = "template";
|
|
||||||
sensors.bedtime_alarm = {
|
|
||||||
friendly_name = "Bedtime Alarm";
|
|
||||||
value_template = "09:00";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
services.mosquitto = {
|
|
||||||
enable = true;
|
|
||||||
listeners = [
|
|
||||||
{
|
|
||||||
acl = [ "pattern readwrite #" ];
|
|
||||||
omitPasswordAuth = true;
|
|
||||||
settings.allow_anonymous = true;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
users.users.hass.extraGroups = [ "dialout" ];
|
|
||||||
system.stateVersion = "23.05";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
{ config, ... }:
|
|
||||||
let
|
|
||||||
unstable = import
|
|
||||||
(builtins.fetchTarball https://github.com/nixos/nixpkgs/tarball/nixpkgs-unstable)
|
|
||||||
# reuse the current configuration
|
|
||||||
{ config = config.nixpkgs.config; };
|
|
||||||
in {
|
|
||||||
services.home-assistant.customComponents = with unstable.home-assistant-custom-components; [
|
|
||||||
epex_spot
|
|
||||||
];
|
|
||||||
|
|
||||||
services.home-assistant.config = {
|
|
||||||
sensor = [
|
|
||||||
{
|
|
||||||
platform = "template";
|
|
||||||
sensors = {
|
|
||||||
electricity_price = {
|
|
||||||
friendly_name = "Current Price of electricity";
|
|
||||||
unit_of_measurement = "EUR/kWh";
|
|
||||||
value_template = ''
|
|
||||||
{{ (((states('sensor.epex_spot_data_price') | int ) / 1000) + (0.0149 + 0.0053 + 0.00866)) | float }}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,403 +0,0 @@
|
|||||||
{
|
|
||||||
services.home-assistant.extraComponents = [
|
|
||||||
"deconz"
|
|
||||||
"shelly"
|
|
||||||
"sun"
|
|
||||||
"nanoleaf"
|
|
||||||
];
|
|
||||||
|
|
||||||
services.home-assistant.config = {
|
|
||||||
homeassistant = {
|
|
||||||
customize_domain = {
|
|
||||||
light = {
|
|
||||||
assumed_state = false;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
"automation light_sunrise" = {
|
|
||||||
alias = "light_sunrise";
|
|
||||||
trigger = {
|
|
||||||
platform = "sun";
|
|
||||||
event = "sunrise";
|
|
||||||
};
|
|
||||||
action = {
|
|
||||||
service = "light.turn_on";
|
|
||||||
target = {
|
|
||||||
entity_id = "{{ states.light | selectattr(\"state\",\"eq\",\"on\") | map(attribute=\"entity_id\") | list }}";
|
|
||||||
};
|
|
||||||
data = {
|
|
||||||
brightness_pct = 254;
|
|
||||||
color_temp = 250;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
"automation light_sunset" = {
|
|
||||||
alias = "light_sunset";
|
|
||||||
trigger = {
|
|
||||||
platform = "sun";
|
|
||||||
event = "sunset";
|
|
||||||
};
|
|
||||||
action = {
|
|
||||||
service = "light.turn_on";
|
|
||||||
target = {
|
|
||||||
entity_id = "{{ states.light | selectattr(\"state\",\"eq\",\"on\") | map(attribute=\"entity_id\") | list }}";
|
|
||||||
};
|
|
||||||
data = {
|
|
||||||
brightness_pct = 30;
|
|
||||||
color_temp = 450;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
"automation light_on" = {
|
|
||||||
alias = "light_on";
|
|
||||||
trigger = {
|
|
||||||
platform = "state";
|
|
||||||
entity_id = [
|
|
||||||
"light.bedroom_lights"
|
|
||||||
"light.kitchen_lights"
|
|
||||||
"light.livingroom_lights"
|
|
||||||
"light.hallway_lights"
|
|
||||||
"light.bathroom_lights"
|
|
||||||
"light.toilett_lights"
|
|
||||||
"light.storage_lights"
|
|
||||||
];
|
|
||||||
to = "on";
|
|
||||||
};
|
|
||||||
action = [
|
|
||||||
{
|
|
||||||
choose = [
|
|
||||||
{
|
|
||||||
conditions = [ "{{ state_attr('sun.sun', 'elevation') < 5 and trigger.entity_id == 'light.toilett_lights' }}" ];
|
|
||||||
sequence = [
|
|
||||||
{
|
|
||||||
delay = 10;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
service = "light.turn_on";
|
|
||||||
target = {
|
|
||||||
entity_id = "{{ trigger.entity_id }}";
|
|
||||||
};
|
|
||||||
data = {
|
|
||||||
brightness_pct = 10;
|
|
||||||
color_temp = 450;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
conditions = [ "{{ state_attr('sun.sun', 'elevation') < 5 and trigger.entity_id == 'light.hallway_lights' }}" ];
|
|
||||||
sequence = [
|
|
||||||
{
|
|
||||||
delay = 10;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
service = "light.turn_on";
|
|
||||||
target = {
|
|
||||||
entity_id = "{{ trigger.entity_id }}";
|
|
||||||
};
|
|
||||||
data = {
|
|
||||||
brightness_pct = 1;
|
|
||||||
color_temp = 450;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
conditions = [ "{{ state_attr('sun.sun', 'elevation') < 5 and trigger.entity_id == 'light.bathroom_lights' }}" ];
|
|
||||||
sequence = [
|
|
||||||
{
|
|
||||||
delay = 10;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
service = "light.turn_on";
|
|
||||||
target = {
|
|
||||||
entity_id = "{{ trigger.entity_id }}";
|
|
||||||
};
|
|
||||||
data = {
|
|
||||||
brightness_pct = 30;
|
|
||||||
color_temp = 450;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
conditions = [ "{{ state_attr('sun.sun', 'elevation') < 5 and trigger.entity_id == 'light.livingroom_lights' }}" ];
|
|
||||||
sequence = [
|
|
||||||
{
|
|
||||||
delay = 10;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
service = "light.turn_on";
|
|
||||||
target = {
|
|
||||||
entity_id = "{{ trigger.entity_id }}";
|
|
||||||
};
|
|
||||||
data = {
|
|
||||||
brightness_pct = 5;
|
|
||||||
color_temp = 450;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
conditions = [ "{{ state_attr('sun.sun', 'elevation') < 5 and trigger.entity_id == 'light.bedroom_lights' }}" ];
|
|
||||||
sequence = [
|
|
||||||
{
|
|
||||||
delay = 10;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
service = "light.turn_on";
|
|
||||||
target = {
|
|
||||||
entity_id = "light.bedroom_lights";
|
|
||||||
};
|
|
||||||
data = {
|
|
||||||
brightness_pct = 5;
|
|
||||||
color_temp = 450;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
conditions = [ "{{ state_attr('sun.sun', 'elevation') < 5 and trigger.entity_id == 'light.kitchen_lights' }}" ];
|
|
||||||
sequence = [
|
|
||||||
{
|
|
||||||
delay = 10;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
service = "light.turn_on";
|
|
||||||
target = {
|
|
||||||
entity_id = "light.kitchen_lights";
|
|
||||||
};
|
|
||||||
data = {
|
|
||||||
brightness_pct = 30;
|
|
||||||
color_temp = 450;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
conditions = [ "{{ state_attr('sun.sun', 'elevation') > 4 }}" ];
|
|
||||||
sequence = [
|
|
||||||
{
|
|
||||||
delay = 10;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
service = "light.turn_on";
|
|
||||||
target = {
|
|
||||||
entity_id = "{{ trigger.entity_id }}";
|
|
||||||
};
|
|
||||||
data = {
|
|
||||||
brightness_pct = 100;
|
|
||||||
color_temp = 250;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
"automation bathroom light small" = {
|
|
||||||
alias = "bathroom light small";
|
|
||||||
mode = "restart";
|
|
||||||
trigger = {
|
|
||||||
platform = "state";
|
|
||||||
entity_id = [
|
|
||||||
"light.bathroom_switch_channel_1"
|
|
||||||
];
|
|
||||||
from = "on";
|
|
||||||
to = "off";
|
|
||||||
};
|
|
||||||
action = [
|
|
||||||
{
|
|
||||||
service = "switch.turn_off";
|
|
||||||
target = {
|
|
||||||
entity_id = "switch.bathroom_small";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
"automation bathroom light" = {
|
|
||||||
alias = "bathroom light";
|
|
||||||
mode = "restart";
|
|
||||||
trigger = {
|
|
||||||
platform = "state";
|
|
||||||
entity_id = [
|
|
||||||
"light.bathroom_switch_channel_1"
|
|
||||||
];
|
|
||||||
from = "off";
|
|
||||||
to = "on";
|
|
||||||
};
|
|
||||||
action = [
|
|
||||||
{
|
|
||||||
delay = 3600;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
service = "light.turn_off";
|
|
||||||
target = {
|
|
||||||
entity_id = "light.bathroom_switch_channel_1";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
"automation bed_led" = {
|
|
||||||
alias = "bed_led";
|
|
||||||
mode = "restart";
|
|
||||||
trigger = {
|
|
||||||
platform = "state";
|
|
||||||
entity_id = [
|
|
||||||
"light.bedroom_led"
|
|
||||||
];
|
|
||||||
from = "off";
|
|
||||||
to = "on";
|
|
||||||
};
|
|
||||||
action = [
|
|
||||||
{
|
|
||||||
delay = 10800;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
service = "light.turn_off";
|
|
||||||
target = {
|
|
||||||
entity_id = "{{ trigger.entity_id }}";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
"automation hallway_motion" = {
|
|
||||||
alias = "Hallway Motion";
|
|
||||||
trigger = {
|
|
||||||
platform = "state";
|
|
||||||
entity_id = "binary_sensor.hallway_motion_motion";
|
|
||||||
};
|
|
||||||
action = {
|
|
||||||
service_template = "light.turn_{{ trigger.to_state.state }}";
|
|
||||||
target = {
|
|
||||||
entity_id = "light.hallway_lights";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
"automation bed_button_1" = {
|
|
||||||
alias = "bed_button_1";
|
|
||||||
trigger = {
|
|
||||||
platform = "event";
|
|
||||||
event_type = "shelly.click";
|
|
||||||
event_data = {
|
|
||||||
device = "shellybutton1-E8DB84AA196D";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
action = [
|
|
||||||
{
|
|
||||||
choose = [
|
|
||||||
{
|
|
||||||
conditions = [ "{{ trigger.event.data.click_type == \"single\" }}" ];
|
|
||||||
sequence = [
|
|
||||||
{
|
|
||||||
service = "light.toggle";
|
|
||||||
entity_id = "light.bed_reading_1";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
conditions = [ "{{ trigger.event.data.click_type == \"double\" }}" ];
|
|
||||||
sequence = [
|
|
||||||
{
|
|
||||||
service = "light.toggle";
|
|
||||||
entity_id = "light.bedroom_lights";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
conditions = [ "{{ trigger.event.data.click_type == \"triple\" }}" ];
|
|
||||||
sequence = [
|
|
||||||
{
|
|
||||||
service = "light.toggle";
|
|
||||||
entity_id = "light.bedroom_bed";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
"automation bed_button_2" = {
|
|
||||||
alias = "bed_button_2";
|
|
||||||
trigger = {
|
|
||||||
platform = "event";
|
|
||||||
event_type = "shelly.click";
|
|
||||||
event_data = {
|
|
||||||
device = "shellybutton1-E8DB84AA136D";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
action = [
|
|
||||||
{
|
|
||||||
choose = [
|
|
||||||
{
|
|
||||||
conditions = [ "{{ trigger.event.data.click_type == \"single\" }}" ];
|
|
||||||
sequence = [
|
|
||||||
{
|
|
||||||
service = "light.toggle";
|
|
||||||
entity_id = "light.bed_reading_2";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
conditions = [ "{{ trigger.event.data.click_type == \"double\" }}" ];
|
|
||||||
sequence = [
|
|
||||||
{
|
|
||||||
service = "light.toggle";
|
|
||||||
entity_id = "light.bedroom_lights";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
conditions = [ "{{ trigger.event.data.click_type == \"triple\" }}" ];
|
|
||||||
sequence = [
|
|
||||||
{
|
|
||||||
service = "light.toggle";
|
|
||||||
entity_id = "light.bedroom_bed";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
light = [
|
|
||||||
{
|
|
||||||
platform = "switch";
|
|
||||||
name = "Livingroom Switch";
|
|
||||||
entity_id = "switch.livingroom_switch";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
platform = "group";
|
|
||||||
name = "Livingroom Lights";
|
|
||||||
all = true;
|
|
||||||
entities = [
|
|
||||||
"light.livingroom_switch"
|
|
||||||
"light.living_bulb_1"
|
|
||||||
"light.living_bulb_2"
|
|
||||||
"light.living_bulb_3"
|
|
||||||
"light.living_bulb_4"
|
|
||||||
"light.living_bulb_5"
|
|
||||||
"light.living_bulb_6"
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
platform = "switch";
|
|
||||||
name = "Bedroom Switch";
|
|
||||||
entity_id = "switch.bedroom_switch";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
platform = "group";
|
|
||||||
name = "Bedroom Lights";
|
|
||||||
all = true;
|
|
||||||
entities = [
|
|
||||||
"light.bedroom_switch"
|
|
||||||
"light.bedroom_bulb_1"
|
|
||||||
"light.bedroom_bulb_2"
|
|
||||||
"light.bedroom_bulb_3"
|
|
||||||
"light.bedroom_bulb_4"
|
|
||||||
];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,436 +0,0 @@
|
|||||||
{
|
|
||||||
services.home-assistant.extraComponents = [
|
|
||||||
"ping"
|
|
||||||
"broadlink"
|
|
||||||
"androidtv"
|
|
||||||
"samsungtv"
|
|
||||||
];
|
|
||||||
services.home-assistant.config = {
|
|
||||||
ios = {
|
|
||||||
actions = [
|
|
||||||
{
|
|
||||||
name = "Home Cinema";
|
|
||||||
label.text = "Home Cinema";
|
|
||||||
icon = {
|
|
||||||
icon = "theater";
|
|
||||||
color = "#ffffff";
|
|
||||||
};
|
|
||||||
show_in_watch = true;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
binary_sensor = [
|
|
||||||
{
|
|
||||||
name = "xbox";
|
|
||||||
platform = "ping";
|
|
||||||
host = "xbox.cloonar.multimedia";
|
|
||||||
count = 2;
|
|
||||||
scan_interval = 5;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "ps5";
|
|
||||||
platform = "ping";
|
|
||||||
host = "ps5.cloonar.multimedia";
|
|
||||||
count = 2;
|
|
||||||
scan_interval = 5;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "steamdeck";
|
|
||||||
platform = "ping";
|
|
||||||
host = "steamdeck.cloonar.com";
|
|
||||||
count = 2;
|
|
||||||
scan_interval = 5;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
platform = "template";
|
|
||||||
sensors = {
|
|
||||||
multimedia_device_on = {
|
|
||||||
friendly_name = "Any multimedia device on";
|
|
||||||
device_class = "connectivity";
|
|
||||||
value_template = ''
|
|
||||||
{% if is_state('binary_sensor.ps5', 'on') or is_state('binary_sensor.xbox', 'on') or (states('media_player.fire_tv_firetv_living_cloonar_multimedia') != 'off' and states('media_player.fire_tv_firetv_living_cloonar_multimedia') != 'unavailable') or (is_state('binary_sensor.steamdeck', 'on') and (states('sensor.steamdeck_power') | float > 5)) %}
|
|
||||||
on
|
|
||||||
{% else %}
|
|
||||||
off
|
|
||||||
{% endif %}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
script = {
|
|
||||||
turn_on_tv = {
|
|
||||||
sequence = [
|
|
||||||
{
|
|
||||||
choose = [
|
|
||||||
{
|
|
||||||
conditions = [
|
|
||||||
{
|
|
||||||
condition = "state";
|
|
||||||
entity_id = "media_player.android_tv_metz_cloonar_multimedia";
|
|
||||||
state = "unavailable";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
sequence = [
|
|
||||||
{
|
|
||||||
service = "remote.send_command";
|
|
||||||
target = {
|
|
||||||
entity_id = "remote.rmproplus";
|
|
||||||
};
|
|
||||||
data = {
|
|
||||||
num_repeats = 1;
|
|
||||||
delay_secs = 0.4;
|
|
||||||
hold_secs = 0;
|
|
||||||
command = "b64:JgBOAJaSFREVNRU2FTUVERURFRAVERURFTUVNhU1FREVERUQFREVERUQFTYVNRURFREVEBURFTYVNRURFRAVNhU1FTYVNRUABfmWkhURFQANBQAAAAAAAAAAAAA=";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
conditions = [
|
|
||||||
{
|
|
||||||
condition = "state";
|
|
||||||
entity_id = "media_player.android_tv_metz_cloonar_multimedia";
|
|
||||||
state = "off";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
sequence = [
|
|
||||||
{
|
|
||||||
service = "media_player.turn_on";
|
|
||||||
target = {
|
|
||||||
entity_id = "media_player.android_tv_metz_cloonar_multimedia";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
"automation steamdeck on" = {
|
|
||||||
alias = "steamdeck on";
|
|
||||||
trigger = {
|
|
||||||
platform = "template";
|
|
||||||
value_template = "{% if is_state('binary_sensor.steamdeck', 'on') and (states('sensor.steamdeck_power') | float > 5) %}true{% endif %}";
|
|
||||||
};
|
|
||||||
action = [
|
|
||||||
{
|
|
||||||
service = "denonavr.get_command";
|
|
||||||
target = {
|
|
||||||
entity_id = "media_player.marantz_sr6015";
|
|
||||||
};
|
|
||||||
data = {
|
|
||||||
command = "/goform/formiPhoneAppDirect.xml?SIDVD";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
"automation xbox on" = {
|
|
||||||
alias = "xbox on";
|
|
||||||
trigger = {
|
|
||||||
platform = "state";
|
|
||||||
entity_id = "binary_sensor.xbox";
|
|
||||||
to = "on";
|
|
||||||
};
|
|
||||||
action = [
|
|
||||||
{
|
|
||||||
service = "denonavr.get_command";
|
|
||||||
target = {
|
|
||||||
entity_id = "media_player.marantz_sr6015";
|
|
||||||
};
|
|
||||||
data = {
|
|
||||||
command = "/goform/formiPhoneAppDirect.xml?SIGAME";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
"automation firetv on" = {
|
|
||||||
alias = "firetv on";
|
|
||||||
trigger = {
|
|
||||||
platform = "state";
|
|
||||||
entity_id = "media_player.fire_tv_firetv_living_cloonar_multimedia";
|
|
||||||
from = "off";
|
|
||||||
};
|
|
||||||
action = [
|
|
||||||
{
|
|
||||||
service = "denonavr.get_command";
|
|
||||||
target = {
|
|
||||||
entity_id = "media_player.marantz_sr6015";
|
|
||||||
};
|
|
||||||
data = {
|
|
||||||
command = "/goform/formiPhoneAppDirect.xml?SIMPLAY";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
"automation ps5 on" = {
|
|
||||||
alias = "ps5 on";
|
|
||||||
trigger = {
|
|
||||||
platform = "state";
|
|
||||||
entity_id = "binary_sensor.ps5";
|
|
||||||
to = "on";
|
|
||||||
};
|
|
||||||
action = [
|
|
||||||
{
|
|
||||||
service = "denonavr.get_command";
|
|
||||||
target = {
|
|
||||||
entity_id = "media_player.marantz_sr6015";
|
|
||||||
};
|
|
||||||
data = {
|
|
||||||
command = "/goform/formiPhoneAppDirect.xml?SIBD";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
"automation all multimedia off" = {
|
|
||||||
alias = "all multimedia off";
|
|
||||||
trigger = {
|
|
||||||
platform = "state";
|
|
||||||
entity_id = "binary_sensor.multimedia_device_on";
|
|
||||||
to = "off";
|
|
||||||
};
|
|
||||||
action = [
|
|
||||||
{
|
|
||||||
service = "media_player.turn_off";
|
|
||||||
target = {
|
|
||||||
entity_id = "media_player.android_tv_metz_cloonar_multimedia";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
{
|
|
||||||
service = "denonavr.get_command";
|
|
||||||
target = {
|
|
||||||
entity_id = "media_player.marantz_sr6015";
|
|
||||||
};
|
|
||||||
data = {
|
|
||||||
command = "/goform/formiPhoneAppDirect.xml?PWSTANDBY";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
# silverscreen up
|
|
||||||
{
|
|
||||||
service = "remote.send_command";
|
|
||||||
target = {
|
|
||||||
entity_id = "remote.rmproplus";
|
|
||||||
};
|
|
||||||
data = {
|
|
||||||
num_repeats = 2;
|
|
||||||
delay_secs = 1;
|
|
||||||
hold_secs = 0;
|
|
||||||
command = "b64:sgBqAgkaBBoJCRsJHBoKGgoJGgQaCQkaBAgbGwoIHAgcGwkJGwgAARkbCRsJGwkJGgQaCgkaBAgbCRsbCQkbGwkJGgQIGxwJGwkJGxsJCRwIHBoKCBsECBsbCAQIGwkAARgbChoKGgoJGxsJCRoECBsJHBsJCRoEGgkJGwkcGgobCQkbGwkJGwkbGwoIHAkbGwkJGwkAARgbCRsJGwoIGxwJCRsJGwkbGwoIGxwIChoKGhwJGwkJHBsJCRsJGxsJCRsJHBsJCRsJAAEYGwkbCRsKCBscCQkbCRsJGxsJCRwbCQkbCRsbCRsJCRscCQgcCRocCQkbCRsbCQobCQABGBsJGwkbCQkbHAkJGwkbCRsbCQkbGwoJGwkbGwkbCQkbGwoIHAkbGwkJGgobGwkKGwkAARccCRsJGwkJHBsJCRsJGwkbGwkJGxsKCRsIHBsJGwkJGxsKCRoJGxwJCRsJGxsJChsIAAEZGwgcCRsJCRscCQkbCRsJGhwJCRscCQkaChsbCRsJCRscCQgcCRocCQkbCRsbCggcCQABGBsJGwkbCggcGwkJGwkbCRsbCggcGgoJGwkbGwkbCggcGwkJGwkbGwkJHAgcGwkJGwkAARgbChoKGgoJGhwJCRsJGwkcGgoJGxsJCRsJGxsJHAkJGxsJCRsJGhwJCRwJGhwJCRsJAAEYGwoaChsJCRsbCQkaChsJGxwJCRsbCQkbCRsbChsJCRsbCQkbCRsbCgkbCRsbCQkcCAABFwQaChsJGwkJGxsKCBwIHAgcGwkJGxsKCBwIGwQaCRsJCRwaCggcCBwbCQkbCRwaCggcCAAF3AAAAAAAAAAAAAAAAAAA";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
# turn off beamer
|
|
||||||
{
|
|
||||||
service = "remote.send_command";
|
|
||||||
target = {
|
|
||||||
entity_id = "remote.rmproplus";
|
|
||||||
};
|
|
||||||
data = {
|
|
||||||
num_repeats = 2;
|
|
||||||
delay_secs = 1;
|
|
||||||
hold_secs = 0;
|
|
||||||
command = "b64:JgDaAAABKZMUERMSExITEhMSExETEhMSExITEhMSExETNxQ2ExITEhMSEzcTNxM3ExITEhM3ExITNxMSEhITEhM3EzcTEhM3EwAFyAABKJQUERMSEhITEhMSExITEhMSEhITEhMSExITNxM3ExITEhMREzcTNxQ3EhITEhM3ExITNxMSExITEhM3EzcTEhM3EwAFyAABKJQUERMSExETEhMSExITEhMSExETEhMSExITNxM3ExITEhMREzcTOBI4ExETEhM3ExITNxMSExITEhM3EzcTEhM3E5IGAA0FAAAAAAAAAAAAAAAAAAA=";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
"automation all_multimedia_on" = {
|
|
||||||
alias = "all multimedia on";
|
|
||||||
trigger = {
|
|
||||||
platform = "state";
|
|
||||||
entity_id = "binary_sensor.multimedia_device_on";
|
|
||||||
to = "on";
|
|
||||||
};
|
|
||||||
action = [
|
|
||||||
{
|
|
||||||
service = "script.turn_on";
|
|
||||||
target = {
|
|
||||||
entity_id = "script.turn_on_tv";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
{
|
|
||||||
delay = 5;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
service = "androidtv.adb_command";
|
|
||||||
target = {
|
|
||||||
entity_id = "media_player.android_tv_metz_cloonar_multimedia";
|
|
||||||
};
|
|
||||||
data = {
|
|
||||||
command = "adb shell am start -a android.intent.action.VIEW -d content://android.media.tv/passthrough/com.mediatek.tvinput%2F.hdmi.HDMIInputService%2FHDMI100004";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
"automation bedroom tv off" = {
|
|
||||||
alias = "bedroom tv off";
|
|
||||||
trigger = {
|
|
||||||
platform = "state";
|
|
||||||
entity_id = "media_player.fire_tv_firetv_bedroom_cloonar_multimedia";
|
|
||||||
to = "off";
|
|
||||||
};
|
|
||||||
action = [
|
|
||||||
{
|
|
||||||
service = "media_player.turn_off";
|
|
||||||
target = {
|
|
||||||
entity_id = "media_player.samsung_7_series_55";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
"automation multimedia scene switch" = {
|
|
||||||
alias = "multimedia scene switch";
|
|
||||||
trigger = [
|
|
||||||
{
|
|
||||||
platform = "event";
|
|
||||||
event_type = "button_pressed";
|
|
||||||
event_data = {
|
|
||||||
id = [ 254 235 105 198 ];
|
|
||||||
onoff = 1;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
{
|
|
||||||
platform = "event";
|
|
||||||
event_type = "ios.action_fired";
|
|
||||||
event_data = {
|
|
||||||
actionID = "Home Cinema";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
condition = {
|
|
||||||
condition = "state";
|
|
||||||
entity_id = "binary_sensor.multimedia_device_on";
|
|
||||||
state = "on";
|
|
||||||
};
|
|
||||||
action = [
|
|
||||||
{
|
|
||||||
choose = [
|
|
||||||
{
|
|
||||||
conditions = [
|
|
||||||
{
|
|
||||||
condition = "or";
|
|
||||||
conditions = [
|
|
||||||
{
|
|
||||||
condition = "state";
|
|
||||||
entity_id = "media_player.android_tv_metz_cloonar_multimedia";
|
|
||||||
state = "on";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
condition = "state";
|
|
||||||
entity_id = "media_player.android_tv_metz_cloonar_multimedia";
|
|
||||||
state = "idle";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
sequence = [
|
|
||||||
# silver screen down
|
|
||||||
{
|
|
||||||
service = "remote.send_command";
|
|
||||||
target = {
|
|
||||||
entity_id = "remote.rmproplus";
|
|
||||||
};
|
|
||||||
data = {
|
|
||||||
num_repeats = 2;
|
|
||||||
delay_secs = 1;
|
|
||||||
hold_secs = 0;
|
|
||||||
command = "b64:sQs0AB0JCxsLGx0IHQgLGh0ICxoLGx0JCxodCQobCxoLAAEXHQgdCR0JCxodCQsbCxsLGx0JCxoAAAAA";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
# turn on beamer
|
|
||||||
{
|
|
||||||
service = "remote.send_command";
|
|
||||||
target = {
|
|
||||||
entity_id = "remote.rmproplus";
|
|
||||||
};
|
|
||||||
data = {
|
|
||||||
num_repeats = 1;
|
|
||||||
delay_secs = 0.4;
|
|
||||||
hold_secs = 0;
|
|
||||||
command = "b64:JgAgAQABKZMUERMSExETEhMSExITEhMSExETEhMSExITNxM3ExITERM3EzgSOBM3ExETEhM3ExITEhMSExITERM3EzcTEhM3EwAFyAABKZMTEhMRExITEhMSExITEhMRExITEhMSExITNxM3ExITERM3EzcTNxM3ExITEhM3ExITEhMSExETEhM3EzcTEhM3EwAFyAABKZMUERMRExITEhMSExITERMSExITEhMSExITNxM3ExISEhM3EzcTNxM3ExITEhM3ExITEhMSExETEhM3EzcTEhM3EwAFxwABKZQUERMRFBETEhMSExITEhISExITEhMSExITNxM3ExITERM3EzcTNxM3FBETEhM3ExITEhMSExITERM3EzcTEhM3EwANBQAAAAAAAAAA";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
{
|
|
||||||
service = "media_player.turn_off";
|
|
||||||
target = {
|
|
||||||
entity_id = "media_player.android_tv_metz_cloonar_multimedia";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
{
|
|
||||||
service = "media_player.turn_on";
|
|
||||||
target = {
|
|
||||||
entity_id = "media_player.marantz_sr6015";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
conditions = [
|
|
||||||
{
|
|
||||||
condition = "or";
|
|
||||||
conditions = [
|
|
||||||
{
|
|
||||||
condition = "state";
|
|
||||||
entity_id = "media_player.android_tv_metz_cloonar_multimedia";
|
|
||||||
state = "off";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
condition = "state";
|
|
||||||
entity_id = "media_player.android_tv_metz_cloonar_multimedia";
|
|
||||||
state = "unavailable";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
sequence = [
|
|
||||||
{
|
|
||||||
service = "remote.send_command";
|
|
||||||
target = {
|
|
||||||
entity_id = "remote.rmproplus";
|
|
||||||
};
|
|
||||||
data = {
|
|
||||||
num_repeats = 2;
|
|
||||||
delay_secs = 1;
|
|
||||||
hold_secs = 0;
|
|
||||||
command = "b64:sgBqAgkaBBoJCRsJHBoKGgoJGgQaCQkaBAgbGwoIHAgcGwkJGwgAARkbCRsJGwkJGgQaCgkaBAgbCRsbCQkbGwkJGgQIGxwJGwkJGxsJCRwIHBoKCBsECBsbCAQIGwkAARgbChoKGgoJGxsJCRoECBsJHBsJCRoEGgkJGwkcGgobCQkbGwkJGwkbGwoIHAkbGwkJGwkAARgbCRsJGwoIGxwJCRsJGwkbGwoIGxwIChoKGhwJGwkJHBsJCRsJGxsJCRsJHBsJCRsJAAEYGwkbCRsKCBscCQkbCRsJGxsJCRwbCQkbCRsbCRsJCRscCQgcCRocCQkbCRsbCQobCQABGBsJGwkbCQkbHAkJGwkbCRsbCQkbGwoJGwkbGwkbCQkbGwoIHAkbGwkJGgobGwkKGwkAARccCRsJGwkJHBsJCRsJGwkbGwkJGxsKCRsIHBsJGwkJGxsKCRoJGxwJCRsJGxsJChsIAAEZGwgcCRsJCRscCQkbCRsJGhwJCRscCQkaChsbCRsJCRscCQgcCRocCQkbCRsbCggcCQABGBsJGwkbCggcGwkJGwkbCRsbCggcGgoJGwkbGwkbCggcGwkJGwkbGwkJHAgcGwkJGwkAARgbChoKGgoJGhwJCRsJGwkcGgoJGxsJCRsJGxsJHAkJGxsJCRsJGhwJCRwJGhwJCRsJAAEYGwoaChsJCRsbCQkaChsJGxwJCRsbCQkbCRsbChsJCRsbCQkbCRsbCgkbCRsbCQkcCAABFwQaChsJGwkJGxsKCBwIHAgcGwkJGxsKCBwIGwQaCRsJCRwaCggcCBwbCQkbCRwaCggcCAAF3AAAAAAAAAAAAAAAAAAA";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
# turn off beamer
|
|
||||||
{
|
|
||||||
service = "remote.send_command";
|
|
||||||
target = {
|
|
||||||
entity_id = "remote.rmproplus";
|
|
||||||
};
|
|
||||||
data = {
|
|
||||||
num_repeats = 2;
|
|
||||||
delay_secs = 1;
|
|
||||||
hold_secs = 0;
|
|
||||||
command = "b64:JgDaAAABKZMUERMSExITEhMSExETEhMSExITEhMSExETNxQ2ExITEhMSEzcTNxM3ExITEhM3ExITNxMSEhITEhM3EzcTEhM3EwAFyAABKJQUERMSEhITEhMSExITEhMSEhITEhMSExITNxM3ExITEhMREzcTNxQ3EhITEhM3ExITNxMSExITEhM3EzcTEhM3EwAFyAABKJQUERMSExETEhMSExITEhMSExETEhMSExITNxM3ExITEhMREzcTOBI4ExETEhM3ExITNxMSExITEhM3EzcTEhM3E5IGAA0FAAAAAAAAAAAAAAAAAAA=";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
{
|
|
||||||
service = "script.turn_on";
|
|
||||||
target = {
|
|
||||||
entity_id = "script.turn_on_tv";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
delay = 5;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
service = "androidtv.adb_command";
|
|
||||||
target = {
|
|
||||||
entity_id = "media_player.android_tv_metz_cloonar_multimedia";
|
|
||||||
};
|
|
||||||
data = {
|
|
||||||
command = "adb shell am start -a android.intent.action.VIEW -d content://android.media.tv/passthrough/com.mediatek.tvinput%2F.hdmi.HDMIInputService%2FHDMI100004";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
{
|
|
||||||
services.home-assistant.config = {
|
|
||||||
"automation toilet music" = {
|
|
||||||
alias = "toilet music";
|
|
||||||
trigger = {
|
|
||||||
platform = "state";
|
|
||||||
entity_id = "light.toilett_lights";
|
|
||||||
};
|
|
||||||
action = [
|
|
||||||
{
|
|
||||||
service = "media_player.volume_mute";
|
|
||||||
target = {
|
|
||||||
entity_id = "media_player.music_toilet_snapcast_client";
|
|
||||||
};
|
|
||||||
data = {
|
|
||||||
is_volume_muted = "{{ trigger.to_state.state == 'off' }}";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,138 +0,0 @@
|
|||||||
{
|
|
||||||
services.home-assistant.extraComponents = [
|
|
||||||
"daikin"
|
|
||||||
"enocean"
|
|
||||||
];
|
|
||||||
|
|
||||||
services.home-assistant.config = {
|
|
||||||
"automation presense kitchen" = {
|
|
||||||
alias = "presense kitchen";
|
|
||||||
mode = "restart";
|
|
||||||
trigger = {
|
|
||||||
platform = "state";
|
|
||||||
entity_id = [
|
|
||||||
"sensor.presense_kitchen"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
action = [
|
|
||||||
{
|
|
||||||
choose = [
|
|
||||||
{
|
|
||||||
conditions = [ "{{ trigger.to_state.state == \"\" }}" ];
|
|
||||||
sequence = [
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
conditions = [ "{{ trigger.to_state.state != \"\" }}" ];
|
|
||||||
sequence = [
|
|
||||||
{
|
|
||||||
service = "light.turn_on";
|
|
||||||
entity_id = "light.kitchen_lights";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
sensor = [
|
|
||||||
{
|
|
||||||
platform = "mqtt_room";
|
|
||||||
device_id = "dominiksiphone";
|
|
||||||
name = "Dominiks iPhone";
|
|
||||||
state_topic = "espresense/devices/dominiksiphone";
|
|
||||||
timeout = 10;
|
|
||||||
away_timeout = 120;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
platform = "template";
|
|
||||||
sensors = {
|
|
||||||
presense_devices = {
|
|
||||||
friendly_name = "Presense Devices";
|
|
||||||
value_template = "dominiks_iphone";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
{
|
|
||||||
platform = "template";
|
|
||||||
sensors = {
|
|
||||||
presense_livingroom = {
|
|
||||||
friendly_name = "Presense Livingroom";
|
|
||||||
value_template = ''
|
|
||||||
{% set room = "livingroom" %}
|
|
||||||
{% set presense = namespace(list=[]) %}
|
|
||||||
{% set presense_list = [] %}
|
|
||||||
{% set device_list = states('sensor.presense_devices').split(',') %}
|
|
||||||
{% for device in device_list %}
|
|
||||||
{% if is_state('sensor.' + device, room) %}
|
|
||||||
{% set presense.list = presense.list + [device] %}
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
{{ presense.list | join("") }}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
{
|
|
||||||
platform = "template";
|
|
||||||
sensors = {
|
|
||||||
presense_kitchen = {
|
|
||||||
friendly_name = "Presense Kitchen";
|
|
||||||
value_template = ''
|
|
||||||
{% set room = "kitchen" %}
|
|
||||||
{% set presense = namespace(list=[]) %}
|
|
||||||
{% set presense_list = [] %}
|
|
||||||
{% set device_list = states('sensor.presense_devices').split(',') %}
|
|
||||||
{% for device in device_list %}
|
|
||||||
{% if is_state('sensor.' + device, room) %}
|
|
||||||
{% set presense.list = presense.list + [device] %}
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
{{ presense.list | join("") }}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
{
|
|
||||||
platform = "template";
|
|
||||||
sensors = {
|
|
||||||
presense_hallway = {
|
|
||||||
friendly_name = "Presense Hallway";
|
|
||||||
value_template = ''
|
|
||||||
{% set room = "hallway" %}
|
|
||||||
{% set presense = namespace(list=[]) %}
|
|
||||||
{% set presense_list = [] %}
|
|
||||||
{% set device_list = states('sensor.presense_devices').split(',') %}
|
|
||||||
{% for device in device_list %}
|
|
||||||
{% if is_state('sensor.' + device, room) %}
|
|
||||||
{% set presense.list = presense.list + [device] %}
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
{{ presense.list | join("") }}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
{
|
|
||||||
platform = "template";
|
|
||||||
sensors = {
|
|
||||||
presense_bedroom = {
|
|
||||||
friendly_name = "Presense Bedroom";
|
|
||||||
value_template = ''
|
|
||||||
{% set room = "bedroom" %}
|
|
||||||
{% set presense = namespace(list=[]) %}
|
|
||||||
{% set presense_list = [] %}
|
|
||||||
{% set device_list = states('sensor.presense_devices').split(',') %}
|
|
||||||
{% for device in device_list %}
|
|
||||||
{% if is_state('sensor.' + device, room) %}
|
|
||||||
{% set presense.list = presense.list + [device] %}
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
{{ presense.list | join("") }}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
{ lib, ... }:
|
|
||||||
let
|
|
||||||
colorbulbs = [
|
|
||||||
{ name = "Living Bulb 1"; id = "34945479BC57"; }
|
|
||||||
{ name = "Living Bulb 2"; id = "485519D9A1B2"; }
|
|
||||||
{ name = "Living Bulb 3"; id = "485519D9AE95"; }
|
|
||||||
{ name = "Living Bulb 4"; id = "485519D94A28"; }
|
|
||||||
{ name = "Living Bulb 5"; id = "485519DA6B6A"; }
|
|
||||||
{ name = "Living Bulb 6"; id = "485519D9E018"; }
|
|
||||||
{ name = "Bedroom Bulb 1"; id = "08f9e06f4eb4"; }
|
|
||||||
{ name = "Bedroom Bulb 2"; id = "485519ee0ed9"; }
|
|
||||||
{ name = "Bedroom Bulb 3"; id = "08f9e06fe779"; }
|
|
||||||
{ name = "Bedroom Bulb 4"; id = "485519ee00a0"; }
|
|
||||||
];
|
|
||||||
|
|
||||||
switches = [];
|
|
||||||
|
|
||||||
proswitches = [
|
|
||||||
{ name = "Livingroom Switch"; id = "shellyplus2pm-e86beae5d5d8"; relay = "0"; }
|
|
||||||
{ name = "Kitchen Switch"; id = "shellyplus2pm-e86beae5d5d8"; relay = "1"; }
|
|
||||||
{ name = "Bedroom Switch"; id = "shelly1pmminig3-34b7da933fe0"; relay = "0"; }
|
|
||||||
{ name = "Hallway Circuit"; id = "shellypro3-c8f09e894448"; relay = "0"; }
|
|
||||||
{ name = "Bathroom Circuit"; id = "shellypro3-c8f09e894448"; relay = "1"; }
|
|
||||||
{ name = "Kitchen Circuit"; id = "shellypro3-c8f09e894448"; relay = "2"; }
|
|
||||||
];
|
|
||||||
in {
|
|
||||||
services.home-assistant.extraComponents = [
|
|
||||||
"shelly"
|
|
||||||
];
|
|
||||||
|
|
||||||
services.home-assistant.config = {
|
|
||||||
mqtt = {
|
|
||||||
switch = builtins.concatLists [
|
|
||||||
(builtins.map (switch:
|
|
||||||
let
|
|
||||||
unique_id = builtins.replaceStrings [" "] ["_"] switch.name;
|
|
||||||
in {
|
|
||||||
name = switch.name;
|
|
||||||
unique_id = unique_id;
|
|
||||||
state_topic = "shellies/shellyswitch25-${switch.id}/relay/${switch.relay}";
|
|
||||||
command_topic = "shellies/shellyswitch25-${switch.id}/relay/${switch.relay}/command";
|
|
||||||
payload_on = "on";
|
|
||||||
payload_off = "off";
|
|
||||||
}
|
|
||||||
) switches)
|
|
||||||
(builtins.map (switch:
|
|
||||||
let
|
|
||||||
unique_id = builtins.replaceStrings [" "] ["_"] switch.name;
|
|
||||||
in {
|
|
||||||
name = switch.name;
|
|
||||||
unique_id = unique_id;
|
|
||||||
state_topic = "shellies/${switch.id}/status/switch:${switch.relay}";
|
|
||||||
value_template = "{{ value_json.output }}";
|
|
||||||
state_on = true;
|
|
||||||
state_off = false;
|
|
||||||
command_topic = "shellies/${switch.id}/rpc";
|
|
||||||
payload_on = "{\"id\":${switch.relay}, \"src\":\"homeassistant\", \"method\":\"Switch.Set\", \"params\":{\"id\":${switch.relay}, \"on\":true}}";
|
|
||||||
payload_off = "{\"id\":${switch.relay}, \"src\":\"homeassistant\", \"method\":\"Switch.Set\", \"params\":{\"id\":${switch.relay}, \"on\":false}}";
|
|
||||||
availability_topic = "shellies/${switch.id}/online";
|
|
||||||
payload_available = "true";
|
|
||||||
payload_not_available = "false";
|
|
||||||
}
|
|
||||||
) proswitches)
|
|
||||||
];
|
|
||||||
light = builtins.map (bulb:
|
|
||||||
let
|
|
||||||
unique_id = builtins.replaceStrings [" "] ["_"] bulb.name;
|
|
||||||
in {
|
|
||||||
name = bulb.name;
|
|
||||||
unique_id = "${unique_id}";
|
|
||||||
schema = "template";
|
|
||||||
state_topic = "shellies/shellycolorbulb-${bulb.id}/color/0/status";
|
|
||||||
state_template = "{% if value_json.ison %}on{% else %}off{% endif %}";
|
|
||||||
command_topic = "shellies/shellycolorbulb-${bulb.id}/color/0/set";
|
|
||||||
command_on_template = ''
|
|
||||||
{
|
|
||||||
"turn": "on",
|
|
||||||
"effect": 0,
|
|
||||||
|
|
||||||
{%- if red is defined and green is defined and blue is defined -%}
|
|
||||||
"mode": "color",
|
|
||||||
"red": {{ red }},
|
|
||||||
"green": {{ green }},
|
|
||||||
"blue": {{ blue }},
|
|
||||||
{%- endif -%}
|
|
||||||
|
|
||||||
{%- if brightness is defined -%}
|
|
||||||
"gain": {{brightness | float | multiply(0.3922) | round(0)}},
|
|
||||||
"brightness": {{brightness | float | multiply(0.3922) | round(0)}},
|
|
||||||
{%- endif -%}
|
|
||||||
|
|
||||||
{% if color_temp is defined %}
|
|
||||||
"mode": "white",
|
|
||||||
"temp":{{ (1/(color_temp | float)) | multiply(1000000) | round(0) }},
|
|
||||||
{% endif %}
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
command_off_template = ''
|
|
||||||
{
|
|
||||||
"turn": "off"
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
brightness_template = "{{ value_json.brightness | float | multiply(2.55) | round(0) }}";
|
|
||||||
color_temp_template = "{{ 1000000 | multiply(1/(value_json.temp | float)) | round(0) }}";
|
|
||||||
red_template = "{{ value_json.red }}";
|
|
||||||
green_template = "{{ value_json.green }}";
|
|
||||||
blue_template = "{{ value_json.blue }}";
|
|
||||||
max_mireds = 333;
|
|
||||||
min_mireds = 154;
|
|
||||||
}) colorbulbs;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
{
|
|
||||||
services.home-assistant.config = {
|
|
||||||
"automation wakeup" = {
|
|
||||||
alias = "wakeup";
|
|
||||||
trigger = {
|
|
||||||
platform = "time";
|
|
||||||
at = "input_datetime.wakeup";
|
|
||||||
};
|
|
||||||
action = [
|
|
||||||
{
|
|
||||||
service = "switch.turn_on";
|
|
||||||
entity_id = "switch.coffee";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
delay = 1700;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
service = "switch.turn_on";
|
|
||||||
entity_id = "switch.78_8c_b5_fe_41_62_port_2_poe"; # livingroom
|
|
||||||
}
|
|
||||||
{
|
|
||||||
service = "switch.turn_on";
|
|
||||||
entity_id = "switch.78_8c_b5_fe_41_62_port_3_poe"; # garden
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
"automation sleep" = {
|
|
||||||
alias = "sleep";
|
|
||||||
trigger = [
|
|
||||||
{
|
|
||||||
platform = "event";
|
|
||||||
event_type = "shelly.click";
|
|
||||||
event_data = {
|
|
||||||
device = "shellybutton1-E8DB84AA196D";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
{
|
|
||||||
platform = "event";
|
|
||||||
event_type = "shelly.click";
|
|
||||||
event_data = {
|
|
||||||
device = "shellybutton1-E8DB84AA136D";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
action = [
|
|
||||||
{
|
|
||||||
choose = [
|
|
||||||
{
|
|
||||||
conditions = [ "{{ trigger.event.data.click_type == \"long\" }}" ];
|
|
||||||
sequence = [
|
|
||||||
{
|
|
||||||
service = "light.turn_off";
|
|
||||||
entity_id = "all";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
service = "switch.turn_off";
|
|
||||||
entity_id = "switch.coffee";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
service = "switch.turn_off";
|
|
||||||
entity_id = "switch.78_8c_b5_fe_41_62_port_2_poe";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
service = "switch.turn_off";
|
|
||||||
entity_id = "switch.78_8c_b5_fe_41_62_port_3_poe";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
{
|
|
||||||
services.home-assistant = {
|
|
||||||
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";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
{ nixpkgs, ...}:
|
|
||||||
{
|
|
||||||
imports = [ (builtins.fetchGit {
|
|
||||||
url = "https://github.com/astro/microvm.nix";
|
|
||||||
} + "/nixos-modules/host") ];
|
|
||||||
|
|
||||||
systemd.network.networks."31-server".matchConfig.Name = [ "vm-*" ];
|
|
||||||
}
|
|
||||||
@@ -1,110 +0,0 @@
|
|||||||
{ ... }: {
|
|
||||||
boot.kernel.sysctl = {
|
|
||||||
# if you use ipv4, this is all you need
|
|
||||||
"net.ipv4.conf.all.forwarding" = true;
|
|
||||||
# If you want to use it for ipv6
|
|
||||||
"net.ipv6.conf.all.forwarding" = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.network = {
|
|
||||||
enable = true;
|
|
||||||
wait-online.anyInterface = true;
|
|
||||||
links = {
|
|
||||||
"10-wan" = {
|
|
||||||
matchConfig.PermanentMACAddress = "c0:74:2b:fd:9a:7f";
|
|
||||||
linkConfig.Name = "wan";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
netdevs = {
|
|
||||||
"30-server".netdevConfig = {
|
|
||||||
Kind = "bridge";
|
|
||||||
Name = "server";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
networks = {
|
|
||||||
"31-server" = {
|
|
||||||
matchConfig.Name = [ "vserver" ];
|
|
||||||
# Attach to the bridge that was configured above
|
|
||||||
networkConfig.Bridge = "server";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
networking = {
|
|
||||||
useDHCP = false;
|
|
||||||
# Define VLANS
|
|
||||||
nameservers = [ "10.42.97.1" ];
|
|
||||||
# resolvconf.enable = false;
|
|
||||||
vlans = {
|
|
||||||
lan = {
|
|
||||||
id = 95;
|
|
||||||
interface = "enP3p49s0";
|
|
||||||
};
|
|
||||||
vserver = {
|
|
||||||
id = 97;
|
|
||||||
interface = "enP3p49s0";
|
|
||||||
};
|
|
||||||
multimedia = {
|
|
||||||
id = 98;
|
|
||||||
interface = "enP3p49s0";
|
|
||||||
};
|
|
||||||
smart = {
|
|
||||||
id = 99;
|
|
||||||
interface = "enP3p49s0";
|
|
||||||
};
|
|
||||||
infrastructure = {
|
|
||||||
id = 100;
|
|
||||||
interface = "enP3p49s0";
|
|
||||||
};
|
|
||||||
guest = {
|
|
||||||
id = 111;
|
|
||||||
interface = "enP3p49s0";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
interfaces = {
|
|
||||||
# Don't request DHCP on the physical interfaces
|
|
||||||
lan.useDHCP = false;
|
|
||||||
enP3p49s0.useDHCP = false;
|
|
||||||
|
|
||||||
# Handle the VLANs
|
|
||||||
wan.useDHCP = true;
|
|
||||||
lan = {
|
|
||||||
ipv4.addresses = [{
|
|
||||||
address = "10.42.95.1";
|
|
||||||
prefixLength = 24;
|
|
||||||
}];
|
|
||||||
};
|
|
||||||
server = {
|
|
||||||
ipv4.addresses = [{
|
|
||||||
address = "10.42.97.1";
|
|
||||||
prefixLength = 24;
|
|
||||||
}];
|
|
||||||
};
|
|
||||||
multimedia = {
|
|
||||||
ipv4.addresses = [{
|
|
||||||
address = "10.42.98.1";
|
|
||||||
prefixLength = 24;
|
|
||||||
}];
|
|
||||||
};
|
|
||||||
smart = {
|
|
||||||
ipv4.addresses = [{
|
|
||||||
address = "10.42.99.1";
|
|
||||||
prefixLength = 24;
|
|
||||||
}];
|
|
||||||
};
|
|
||||||
infrastructure = {
|
|
||||||
ipv4.addresses = [{
|
|
||||||
address = "10.42.100.1";
|
|
||||||
prefixLength = 24;
|
|
||||||
}];
|
|
||||||
};
|
|
||||||
guest = {
|
|
||||||
ipv4.addresses = [{
|
|
||||||
address = "10.42.111.1";
|
|
||||||
prefixLength = 24;
|
|
||||||
}];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,133 +0,0 @@
|
|||||||
{ pkgs, config, python3Packages, ... }:
|
|
||||||
let
|
|
||||||
domain = "snapcast.cloonar.com";
|
|
||||||
|
|
||||||
snapweb = pkgs.stdenv.mkDerivation {
|
|
||||||
pname = "snapweb";
|
|
||||||
version = "0.8";
|
|
||||||
|
|
||||||
src = pkgs.fetchzip {
|
|
||||||
url = "https://github.com/badaix/snapweb/releases/download/v0.8.0/snapweb.zip";
|
|
||||||
sha256 = "sha256-IpT1pcuzcM8kqWJUX3xxpRQHlfPNsrwhemLmY0PyzjI=";
|
|
||||||
stripRoot = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
installPhase = ''
|
|
||||||
mkdir -p $out
|
|
||||||
cp -r $src/* $out/
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
security.acme.certs."${domain}" = {
|
|
||||||
group = "nginx";
|
|
||||||
};
|
|
||||||
|
|
||||||
containers.snapcast = {
|
|
||||||
autoStart = true;
|
|
||||||
ephemeral = false; # because of ssh key
|
|
||||||
privateNetwork = true;
|
|
||||||
hostBridge = "server";
|
|
||||||
hostAddress = "10.42.97.1";
|
|
||||||
localAddress = "10.42.97.21/24";
|
|
||||||
bindMounts = {
|
|
||||||
"/var/lib/acme/snapcast/" = {
|
|
||||||
hostPath = "${config.security.acme.certs.${domain}.directory}";
|
|
||||||
isReadOnly = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
config = { lib, config, pkgs, python3Packages, ... }:
|
|
||||||
let
|
|
||||||
shairport-sync = pkgs.shairport-sync.overrideAttrs (_: {
|
|
||||||
configureFlags = [
|
|
||||||
"--with-alsa" "--with-pipe" "--with-pa" "--with-stdout"
|
|
||||||
"--with-avahi" "--with-ssl=openssl" "--with-soxr"
|
|
||||||
"--without-configfiles"
|
|
||||||
"--sysconfdir=/etc"
|
|
||||||
"--with-metadata"
|
|
||||||
];
|
|
||||||
});
|
|
||||||
in
|
|
||||||
{
|
|
||||||
networking = {
|
|
||||||
hostName = "snapcast";
|
|
||||||
useHostResolvConf = false;
|
|
||||||
defaultGateway = {
|
|
||||||
address = "10.42.96.1";
|
|
||||||
interface = "eth0";
|
|
||||||
};
|
|
||||||
nameservers = [ "10.42.97.1" ];
|
|
||||||
firewall.enable = false;
|
|
||||||
};
|
|
||||||
environment.etc = {
|
|
||||||
# Creates /etc/nanorc
|
|
||||||
shairport = {
|
|
||||||
text = ''
|
|
||||||
whatever you want to put in the file goes here.
|
|
||||||
metadata =
|
|
||||||
{
|
|
||||||
enabled = "yes"; // set this to yes to get Shairport Sync to solicit metadata from the source and to pass it on via a pipe
|
|
||||||
include_cover_art = "yes"; // set to "yes" to get Shairport Sync to solicit cover art from the source and pass it via the pipe. You must also set "enabled" to "yes".
|
|
||||||
cover_art_cache_directory = "/tmp/shairport-sync/.cache/coverart"; // artwork will be stored in this directory if the dbus or MPRIS interfaces are enabled or if the MQTT client is in use. Set it to "" to prevent caching, which may be useful on some systems
|
|
||||||
pipe_name = "/tmp/shairport-sync-metadata";
|
|
||||||
pipe_timeout = 5000; // wait for this number of milliseconds for a blocked pipe to unblock before giving up
|
|
||||||
};
|
|
||||||
'';
|
|
||||||
|
|
||||||
# The UNIX file mode bits
|
|
||||||
mode = "0440";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
services.snapserver = {
|
|
||||||
enable = true;
|
|
||||||
codec = "flac";
|
|
||||||
http.enable = true;
|
|
||||||
http.docRoot = "${snapweb}/";
|
|
||||||
streams.mopidy = {
|
|
||||||
type = "pipe";
|
|
||||||
location = "/run/snapserver/mopidy";
|
|
||||||
};
|
|
||||||
streams.airplay = {
|
|
||||||
type = "airplay";
|
|
||||||
location = "${shairport-sync}/bin/shairport-sync";
|
|
||||||
query = {
|
|
||||||
devicename = "Multi Room New";
|
|
||||||
port = "5000";
|
|
||||||
params = "--mdns=avahi";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
streams.mixed = {
|
|
||||||
type = "meta";
|
|
||||||
location = "/airplay/mopidy";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
services.avahi.enable = true;
|
|
||||||
services.avahi.publish.enable = true;
|
|
||||||
services.avahi.publish.userServices = true;
|
|
||||||
|
|
||||||
services.nginx.enable = true;
|
|
||||||
services.nginx.virtualHosts."snapcast.cloonar.com" = {
|
|
||||||
sslCertificate = "/var/lib/acme/snapcast/fullchain.pem";
|
|
||||||
sslCertificateKey = "/var/lib/acme/snapcast/key.pem";
|
|
||||||
sslTrustedCertificate = "/var/lib/acme/snapcast/chain.pem";
|
|
||||||
forceSSL = true;
|
|
||||||
extraConfig = ''
|
|
||||||
proxy_buffering off;
|
|
||||||
'';
|
|
||||||
locations."/".extraConfig = ''
|
|
||||||
proxy_pass http://127.0.0.1:1780;
|
|
||||||
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";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
{
|
|
||||||
uids = {
|
|
||||||
unbound = 10001;
|
|
||||||
gitea = 10002;
|
|
||||||
gitea-runner = 10003;
|
|
||||||
podman = 10004;
|
|
||||||
};
|
|
||||||
gids = {
|
|
||||||
unbound = 10001;
|
|
||||||
gitea = 10002;
|
|
||||||
gitea-runner = 10003;
|
|
||||||
podman = 10004;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,339 +0,0 @@
|
|||||||
{ config, pkgs, ... }:
|
|
||||||
let
|
|
||||||
cids = import ../modules/staticids.nix;
|
|
||||||
domain = "ns.cloonar.com";
|
|
||||||
|
|
||||||
adblockLocalZones = pkgs.stdenv.mkDerivation {
|
|
||||||
name = "unbound-zones-adblock";
|
|
||||||
|
|
||||||
src = (pkgs.fetchFromGitHub {
|
|
||||||
owner = "StevenBlack";
|
|
||||||
repo = "hosts";
|
|
||||||
rev = "3.0.0";
|
|
||||||
sha256 = "01g6pc9s1ah2w1cbf6bvi424762hkbpbgja9585a0w99cq0n6bxv";
|
|
||||||
} + "/hosts");
|
|
||||||
|
|
||||||
phases = [ "installPhase" ];
|
|
||||||
|
|
||||||
installPhase = ''
|
|
||||||
${pkgs.gawk}/bin/awk '{sub(/\r$/,"")} {sub(/^127\.0\.0\.1/,"0.0.0.0")} BEGIN { OFS = "" } NF == 2 && $1 == "0.0.0.0" { print "local-zone: \"", $2, "\" static"}' $src | tr '[:upper:]' '[:lower:]' | sort -u > $out
|
|
||||||
'';
|
|
||||||
|
|
||||||
};
|
|
||||||
cfg = {
|
|
||||||
remote-control.control-enable = true;
|
|
||||||
server = {
|
|
||||||
include = [
|
|
||||||
"\"${adblockLocalZones}\""
|
|
||||||
];
|
|
||||||
interface = [ "0.0.0.0" "::0" ];
|
|
||||||
interface-automatic = "yes";
|
|
||||||
access-control = [
|
|
||||||
"127.0.0.0/8 allow"
|
|
||||||
"10.42.96.0/24 allow"
|
|
||||||
"10.42.97.0/24 allow"
|
|
||||||
"10.42.98.0/24 allow"
|
|
||||||
"10.42.99.0/24 allow"
|
|
||||||
"10.42.101.0/24 allow"
|
|
||||||
"0.0.0.0/0 allow"
|
|
||||||
];
|
|
||||||
tls-cert-bundle = "/etc/ssl/certs/ca-certificates.crt";
|
|
||||||
local-zone = "\"cloonar.com\" transparent";
|
|
||||||
local-data = [
|
|
||||||
"\"localhost A 127.0.0.1\""
|
|
||||||
"\"localhost.cloonar.com A 127.0.0.1\""
|
|
||||||
"\"localhost AAAA ::1\""
|
|
||||||
"\"localhost.cloonar.com AAAA ::1\""
|
|
||||||
"\"fw.cloonar.com A 10.42.97.1\""
|
|
||||||
"\"fw A 10.42.97.1\""
|
|
||||||
|
|
||||||
"\"pc.cloonar.com IN A 10.42.96.5\""
|
|
||||||
"\"omada.cloonar.com IN A 10.42.97.2\""
|
|
||||||
"\"switch.cloonar.com IN A 10.42.97.10\""
|
|
||||||
"\"mopidy.cloonar.com IN A 10.42.97.21\""
|
|
||||||
"\"deconz.cloonar.com IN A 10.42.97.22\""
|
|
||||||
"\"brn30055c566237.cloonar.com IN A 10.42.96.100\""
|
|
||||||
"\"snapcast.cloonar.com IN A 10.42.97.21\""
|
|
||||||
"\"home-assistant.cloonar.com IN A 10.42.97.20\""
|
|
||||||
"\"web-02.cloonar.com IN A 10.42.97.5\""
|
|
||||||
"\"support.cloonar.com IN A 10.42.97.5\""
|
|
||||||
"\"git.cloonar.com IN A 10.42.97.50\""
|
|
||||||
"\"sync.cloonar.com IN A 10.42.97.51\""
|
|
||||||
|
|
||||||
"\"feeds.cloonar.com IN A 188.34.191.144\""
|
|
||||||
# "\"paraclub.cloonar.dev IN A 49.12.244.139\""
|
|
||||||
# "\"api.paraclub.cloonar.dev IN A 49.12.244.139\""
|
|
||||||
# "\"module.paraclub.cloonar.dev IN A 49.12.244.139\""
|
|
||||||
# "\"tandem.paraclub.cloonar.dev IN A 49.12.244.139\""
|
|
||||||
|
|
||||||
"\"stage.wsw.at IN A 10.254.235.22\""
|
|
||||||
"\"prod.wsw.at IN A 10.254.217.23\""
|
|
||||||
"\"piwik.wohnservice-wien.at IN A 10.254.240.109\""
|
|
||||||
"\"wohnservice-wien.at IN A 10.254.240.109\""
|
|
||||||
"\"mieterhilfe.at IN A 10.254.240.109\""
|
|
||||||
"\"wohnpartner-wien.at IN A 10.254.240.109\""
|
|
||||||
"\"new.wohnberatung-wien.at IN A 10.254.240.109\""
|
|
||||||
"\"wohnberatung-wien.at IN A 10.254.240.109\""
|
|
||||||
"\"wienbautvor.at IN A 10.254.240.109\""
|
|
||||||
"\"wienwohntbesser.at IN A 10.254.240.109\""
|
|
||||||
"\"b.wohnservice-wien.at IN A 10.254.240.109\""
|
|
||||||
"\"b.mieterhilfe.at IN A 10.254.240.109\""
|
|
||||||
"\"b.wohnpartner-wien.at IN A 10.254.240.109\""
|
|
||||||
"\"b.wohnberatung-wien.at IN A 10.254.240.109\""
|
|
||||||
"\"b.wienbautvor.at IN A 10.254.240.109\""
|
|
||||||
"\"b.wienwohntbesser.at IN A 10.254.240.109\""
|
|
||||||
"\"a.wohnservice-wien.at IN A 10.254.240.109\""
|
|
||||||
"\"a.wohnpartner-wien.at IN A 10.254.240.109\""
|
|
||||||
"\"a.stage.wohnservice-wien.at IN A 10.254.240.110\""
|
|
||||||
"\"a.stage.mieterhilfe.at IN A 10.254.240.110\""
|
|
||||||
"\"a.stage.wohnpartner-wien.at IN A 10.254.240.110\""
|
|
||||||
"\"a.stage.wohnberatung-wien.at IN A 10.254.240.110\""
|
|
||||||
"\"a.stage.wienbautvor.at IN A 10.254.240.110\""
|
|
||||||
"\"a.stage.wienwohntbesser.at IN A 10.254.240.110\""
|
|
||||||
"\"b.stage.wohnservice-wien.at IN A 10.254.240.110\""
|
|
||||||
"\"b.stage.mieterhilfe.at IN A 10.254.240.110\""
|
|
||||||
"\"b.stage.wohnpartner-wien.at IN A 10.254.240.110\""
|
|
||||||
"\"b.stage.new.wohnberatung-wien.at IN A 10.254.240.110\""
|
|
||||||
"\"b.stage.wohnberatung-wien.at IN A 10.254.240.110\""
|
|
||||||
"\"b.stage.wienbautvor.at IN A 10.254.240.110\""
|
|
||||||
"\"b.stage.wienwohntbesser.at IN A 10.254.240.110\""
|
|
||||||
"\"upgrade-staging.wohnservice-wien.at IN A 10.254.240.110\""
|
|
||||||
"\"upgrade-staging.mieterhilfe.at IN A 10.254.240.110\""
|
|
||||||
"\"upgrade-staging.wohnpartner-wien.at IN A 10.254.240.110\""
|
|
||||||
"\"upgrade-staging.wohnberatung-wien.at IN A 10.254.240.110\""
|
|
||||||
"\"upgrade-staging.wienbautvor.at IN A 10.254.240.110\""
|
|
||||||
"\"upgrade-staging.wienwohntbesser.at IN A 10.254.240.110\""
|
|
||||||
"\"conf.wrwks.at IN A 10.254.240.105\""
|
|
||||||
|
|
||||||
"\"web.hilgenberg-gmbh.de IN A 91.107.197.169\""
|
|
||||||
|
|
||||||
"\"deconz.cloonar.multimedia IN A 10.42.97.22\""
|
|
||||||
"\"metz.cloonar.multimedia IN A 10.42.99.10\""
|
|
||||||
# "\"ps5.cloonar.multimedia IN A 10.42.99.12\""
|
|
||||||
"\"xbox.cloonar.multimedia IN A 10.42.99.13\""
|
|
||||||
# "\"switch.cloonar.multimedia IN A 10.42.99.14\""
|
|
||||||
#living room
|
|
||||||
"\"shellycolorbulb-livingroom-1.cloonar.smart IN A 10.42.100.2\""
|
|
||||||
"\"shellycolorbulb-livingroom-2.cloonar.smart IN A 10.42.100.3\""
|
|
||||||
"\"shellycolorbulb-livingroom-3.cloonar.smart IN A 10.42.100.4\""
|
|
||||||
"\"shellycolorbulb-livingroom-4.cloonar.smart IN A 10.42.100.5\""
|
|
||||||
"\"shellycolorbulb-livingroom-5.cloonar.smart IN A 10.42.100.6\""
|
|
||||||
"\"shellycolorbulb-livingroom-6.cloonar.smart IN A 10.42.100.7\""
|
|
||||||
"\"shellyuni-livingroom-1.cloonar.smart IN A 10.42.100.8\""
|
|
||||||
"\"shellyswitch25-livingroom-1.cloonar.smart IN A 10.42.100.9\""
|
|
||||||
"\"shellyplug-s-living-1.cloonar.smart IN A 10.42.100.10\""
|
|
||||||
"\"shellyplug-s-living-2.cloonar.smart IN A 10.42.100.11\""
|
|
||||||
# kitchen
|
|
||||||
"\"shellyplug-s-kitchen-1.cloonar.smart IN A 10.42.100.17\""
|
|
||||||
"\"shellyrgbw2-kitchen-1.cloonar.smart IN A 10.42.100.18\""
|
|
||||||
#bedroom
|
|
||||||
"\"shelly1-bedroom-1.cloonar.smart IN A 10.42.100.33\""
|
|
||||||
"\"shellybutton1-bedroom-1.cloonar.smart IN A 10.42.100.34\""
|
|
||||||
"\"shellybutton1-bedroom-2.cloonar.smart IN A 10.42.100.35\"" # todo
|
|
||||||
"\"shellyrgbw2-bedroom-1.cloonar.smart IN A 10.42.100.36\""
|
|
||||||
"\"shellyrgbw2-bedroom-2.cloonar.smart IN A 10.42.100.37\""
|
|
||||||
"\"shellyrgbw2-bedroom-3.cloonar.smart IN A 10.42.100.38\""
|
|
||||||
"\"shellycolorbulb-bedroom-1.cloonar.smart IN A 10.42.100.39\""
|
|
||||||
"\"shellycolorbulb-bedroom-2.cloonar.smart IN A 10.42.100.40\""
|
|
||||||
"\"shellycolorbulb-bedroom-3.cloonar.smart IN A 10.42.100.41\""
|
|
||||||
"\"shellycolorbulb-bedroom-4.cloonar.smart IN A 10.42.100.42\""
|
|
||||||
# bath
|
|
||||||
"\"shellyswitch25-bath-1.cloonar.smart IN A 10.42.100.49\""
|
|
||||||
"\"shellybulbduo-bath-1.cloonar.smart IN A 10.42.100.50\""
|
|
||||||
"\"shellybulbduo-bath-2.cloonar.smart IN A 10.42.100.51\""
|
|
||||||
"\"shelly1pm-bath-1.cloonar.smart IN A 10.42.100.52\""
|
|
||||||
"\"shellyht-bath-1.cloonar.smart IN A 10.42.100.53\"" # todo
|
|
||||||
# hallway
|
|
||||||
"\"shelly1-hallway-1.cloonar.smart IN A 10.42.100.65\""
|
|
||||||
"\"shellycolorbulb-hallway-1.cloonar.smart IN A 10.42.100.66\""
|
|
||||||
"\"shellycolorbulb-hallway-2.cloonar.smart IN A 10.42.100.67\""
|
|
||||||
"\"shellycolorbulb-hallway-3.cloonar.smart IN A 10.42.100.68\""
|
|
||||||
"\"shellycolorbulb-hallway-4.cloonar.smart IN A 10.42.100.69\""
|
|
||||||
"\"shellyem3.cloonar.smart IN A 10.42.100.70\""
|
|
||||||
"\"shellypro-1.cloonar.smart IN A 10.42.100.71\""
|
|
||||||
"\"shellypro-2.cloonar.smart IN A 10.42.100.72\""
|
|
||||||
# toilet
|
|
||||||
"\"shelly1-toilet-1.cloonar.smart IN A 10.42.100.81\""
|
|
||||||
"\"shellybulbduo-toilet-1.cloonar.smart IN A 10.42.100.82\""
|
|
||||||
# storage
|
|
||||||
"\"shelly1-storage-1.cloonar.smart IN A 10.42.100.97\""
|
|
||||||
"\"shellyplug-storage-1.cloonar.smart IN A 10.42.100.98\""
|
|
||||||
"\"brn30055c566237.cloonar.multimedia IN A 10.42.99.100\""
|
|
||||||
|
|
||||||
"\"ddl-warez.to IN A 172.67.184.30\""
|
|
||||||
"\"cdnjs.cloudflare.com IN A 104.17.24.14\""
|
|
||||||
];
|
|
||||||
local-data-ptr = [
|
|
||||||
"\"127.0.0.1 localhost\""
|
|
||||||
"\"::1 localhost\""
|
|
||||||
"\"10.42.97.1 fw.cloonar.com\""
|
|
||||||
"\"10.42.97.20 home-assistant.cloonar.com\""
|
|
||||||
"\"10.42.97.21 snapcast.cloonar.com\""
|
|
||||||
"\"10.42.97.22 deconz.cloonar.com\""
|
|
||||||
"\"10.42.97.50 git.cloonar.com\""
|
|
||||||
|
|
||||||
"\"10.254.235.22 stage.wsw.at\""
|
|
||||||
"\"10.254.217.23 prod.wsw.at\""
|
|
||||||
"\"10.254.240.109 wohnservice-wien.at\""
|
|
||||||
"\"10.254.240.110 a.stage.wohnservice-wien.at\""
|
|
||||||
|
|
||||||
"\"172.67.184.30 ddl-warez.to\""
|
|
||||||
"\"104.17.24.14 cdnjs.cloudflare.com\""
|
|
||||||
];
|
|
||||||
# ssl-upstream = "yes";
|
|
||||||
};
|
|
||||||
forward-zone = [
|
|
||||||
{
|
|
||||||
name = "local.ghetto.at.";
|
|
||||||
forward-tls-upstream = "no";
|
|
||||||
forward-addr = [
|
|
||||||
"10.43.97.1"
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "ghetto.at.local.";
|
|
||||||
forward-tls-upstream = "no";
|
|
||||||
forward-addr = [
|
|
||||||
"10.43.97.1"
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "epicenter.works.";
|
|
||||||
forward-tls-upstream = "no";
|
|
||||||
forward-addr = [
|
|
||||||
"10.50.60.1"
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "akvorrat.at.";
|
|
||||||
forward-tls-upstream = "no";
|
|
||||||
forward-addr = [
|
|
||||||
"10.50.60.1"
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "epicenter.intra.";
|
|
||||||
forward-tls-upstream = "no";
|
|
||||||
forward-addr = [
|
|
||||||
"10.14.1.1"
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "intra.epicenter.works.";
|
|
||||||
forward-tls-upstream = "no";
|
|
||||||
forward-addr = [
|
|
||||||
"10.14.1.1"
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = ".";
|
|
||||||
forward-tls-upstream = "yes";
|
|
||||||
forward-first = "no";
|
|
||||||
forward-addr = [
|
|
||||||
"9.9.9.9@853#dns9.quad9.net"
|
|
||||||
"149.112.112.11@853#dns11.quad9.net"
|
|
||||||
];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
in {
|
|
||||||
users.users.unbound = {
|
|
||||||
group = "unbound";
|
|
||||||
isSystemUser = true;
|
|
||||||
uid = cids.uids.unbound;
|
|
||||||
};
|
|
||||||
users.groups.unbound = {
|
|
||||||
gid = cids.gids.unbound;
|
|
||||||
};
|
|
||||||
|
|
||||||
security.acme.certs."${domain}" = {
|
|
||||||
group = "unbound";
|
|
||||||
};
|
|
||||||
security.acme.certs."fw.cloonar.com" = {
|
|
||||||
group = "unbound";
|
|
||||||
};
|
|
||||||
|
|
||||||
services.resolved.enable = false;
|
|
||||||
|
|
||||||
services.unbound = {
|
|
||||||
enable = true;
|
|
||||||
settings = cfg;
|
|
||||||
};
|
|
||||||
# systemd.services.unbound-sync = {
|
|
||||||
# enable = true;
|
|
||||||
# path = with pkgs; [ unbound inotify-tools ];
|
|
||||||
# script = ''
|
|
||||||
# function readFile() {
|
|
||||||
# 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
|
|
||||||
# do
|
|
||||||
# echo "''\${address},''\${hostname}"
|
|
||||||
# done
|
|
||||||
# else
|
|
||||||
# cat "''\$1" | tail -n +2 | while IFS=, read -r address duid valid_lifetime expire subnet_id pref_lifetime lease_type iaid prefix_len fqdn_fwd fqdn_rev hostname hwaddr state user_context hwtype hwaddr_source
|
|
||||||
# do
|
|
||||||
# echo "''\${address},''\${hostname}"
|
|
||||||
# done
|
|
||||||
# fi
|
|
||||||
# }
|
|
||||||
#
|
|
||||||
# function readFileUnique() {
|
|
||||||
# readFile "''\$1" ''\$2 | uniq | while IFS=, read -r address hostname
|
|
||||||
# do
|
|
||||||
# if echo "''\${1}" | grep -Eq '.*\.(cloonar.com|cloonar.multimedia|cloonar.smart)'; then
|
|
||||||
# echo ''\${hostname} ''\$2 ''\${address}
|
|
||||||
# unbound-control local_data ''\${hostname} ''\$2 ''\${address}
|
|
||||||
# if [[ "''\$2" == "A" ]] ; then
|
|
||||||
# echo ''\${address} | while IFS=. read -r ip0 ip1 ip2 ip3
|
|
||||||
# do
|
|
||||||
# unbound-control local_data ''\${ip3}.''\${ip2}.''\${ip1}.''\${ip0}.ip4.arpa. PTR ''\${hostname}
|
|
||||||
# unbound-control local_data ''\${ip3}.''\${ip2}.''\${ip1}.''\${ip0}.in-addr.arpa. PTR ''\${hostname}
|
|
||||||
# done
|
|
||||||
# fi
|
|
||||||
# else
|
|
||||||
# if [[ "''\$2" == "A" ]] ; then
|
|
||||||
# echo ''\${address} | while IFS=. read -r ip0 ip1 ip2 ip3
|
|
||||||
# do
|
|
||||||
# if [[ "''\${hostname}" != "" ]]; then
|
|
||||||
# domain=cloonar.com
|
|
||||||
# if [[ "''\${ip2}" == 99 ]]; then
|
|
||||||
# domain=cloonar.multimedia
|
|
||||||
# fi
|
|
||||||
# if [[ "''\${ip2}" == 100 ]]; then
|
|
||||||
# domain=cloonar.smart
|
|
||||||
# fi
|
|
||||||
# if [[ "''\${hostname}" != *. ]]; then
|
|
||||||
# unbound-control local_data ''\${hostname}.''\${domain} ''\$2 ''\${address}
|
|
||||||
# else
|
|
||||||
# unbound-control local_data ''\${hostname}''\${domain} ''\$2 ''\${address}
|
|
||||||
# fi
|
|
||||||
#
|
|
||||||
# fi
|
|
||||||
# unbound-control local_data ''\${ip3}.''\${ip2}.''\${ip1}.''\${ip0}.ip4.arpa. PTR ''\${hostname}
|
|
||||||
# unbound-control local_data ''\${ip3}.''\${ip2}.''\${ip1}.''\${ip0}.in-addr.arpa. PTR ''\${hostname}
|
|
||||||
# done
|
|
||||||
# fi
|
|
||||||
# fi
|
|
||||||
# done
|
|
||||||
# }
|
|
||||||
#
|
|
||||||
# function syncFile() {
|
|
||||||
# # readFileUnique "''\$1" "''\$2"
|
|
||||||
# while true; do
|
|
||||||
# readFileUnique "''\$1" "''\$2"
|
|
||||||
# sleep 10
|
|
||||||
# done
|
|
||||||
# }
|
|
||||||
#
|
|
||||||
# syncFile "/var/lib/kea/dhcp4.leases" A &
|
|
||||||
# # syncFile "/var/lib/kea/dhcp6.leases" AAAA &
|
|
||||||
# wait
|
|
||||||
# '';
|
|
||||||
# wants = [ "network-online.target" "unbound.service" ];
|
|
||||||
# after = [ "network-online.target" "unbound.service" ];
|
|
||||||
# partOf = [ "unbound.service" ];
|
|
||||||
# wantedBy = [ "multi-user.target" ];
|
|
||||||
# };
|
|
||||||
|
|
||||||
networking.firewall.allowedUDPPorts = [ 53 5353 ];
|
|
||||||
}
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
{ lib, nixpkgs, pkgs, ... }: let
|
|
||||||
hostname = "web-02";
|
|
||||||
json = pkgs.formats.json { };
|
|
||||||
impermanence = builtins.fetchTarball "https://github.com/nix-community/impermanence/archive/master.tar.gz";
|
|
||||||
in {
|
|
||||||
microvm.vms = {
|
|
||||||
web = {
|
|
||||||
config = {
|
|
||||||
microvm = {
|
|
||||||
mem = 4096;
|
|
||||||
# hypervisor = "cloud-hypervisor";
|
|
||||||
shares = [
|
|
||||||
{
|
|
||||||
source = "/nix/store";
|
|
||||||
mountPoint = "/nix/.ro-store";
|
|
||||||
tag = "ro-store";
|
|
||||||
proto = "virtiofs";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
source = "/var/lib/microvms/persist/web-02";
|
|
||||||
mountPoint = "/persist";
|
|
||||||
tag = "persist";
|
|
||||||
proto = "virtiofs";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
volumes = [
|
|
||||||
{
|
|
||||||
image = "rootfs.img";
|
|
||||||
mountPoint = "/";
|
|
||||||
size = 102400;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
interfaces = [
|
|
||||||
{
|
|
||||||
type = "tap";
|
|
||||||
id = "vm-${hostname}";
|
|
||||||
mac = "02:00:00:00:00:03";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
imports = [
|
|
||||||
"${impermanence}/nixos.nix"
|
|
||||||
../../utils/modules/sops.nix
|
|
||||||
../../utils/modules/lego/lego.nix
|
|
||||||
# ../../utils/modules/borgbackup.nix
|
|
||||||
|
|
||||||
# ./zammad.nix
|
|
||||||
./proxies.nix
|
|
||||||
];
|
|
||||||
|
|
||||||
time.timeZone = "Europe/Vienna";
|
|
||||||
|
|
||||||
systemd.network.networks."10-lan" = {
|
|
||||||
matchConfig.PermanentMACAddress = "02:00:00:00:00:03";
|
|
||||||
address = [ "10.42.97.5/24" ];
|
|
||||||
gateway = [ "10.42.97.1" ];
|
|
||||||
dns = [ "10.42.97.1" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
fileSystems."/persist".neededForBoot = lib.mkForce true;
|
|
||||||
environment.persistence."/persist-local" = {
|
|
||||||
directories = [
|
|
||||||
"/var/lib/zammad"
|
|
||||||
"/var/lib/postgresql"
|
|
||||||
"/var/log"
|
|
||||||
"/var/lib/systemd/coredump"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; [
|
|
||||||
vim # my preferred editor
|
|
||||||
];
|
|
||||||
|
|
||||||
networking.hostName = hostname;
|
|
||||||
|
|
||||||
services.openssh = {
|
|
||||||
enable = true;
|
|
||||||
hostKeys = [
|
|
||||||
{
|
|
||||||
path = "/persist/etc/ssh/ssh_host_ed25519_key";
|
|
||||||
type = "ed25519";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
path = "/persist/etc/ssh/ssh_host_rsa_key";
|
|
||||||
type = "rsa";
|
|
||||||
bits = 4096;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
users.users.root.openssh.authorizedKeys.keys = [
|
|
||||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7"
|
|
||||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIRQuPqH5fdX3KEw7DXzWEdO3AlUn1oSmtJtHB71ICoH Generated By Termius"
|
|
||||||
];
|
|
||||||
|
|
||||||
# backups
|
|
||||||
# borgbackup.repo = "u149513-sub2@u149513-sub2.your-backup.de:borg";
|
|
||||||
|
|
||||||
|
|
||||||
sops.age.sshKeyPaths = [ "/persist/etc/ssh/ssh_host_ed25519_key" ];
|
|
||||||
sops.defaultSopsFile = ./secrets.yaml;
|
|
||||||
|
|
||||||
networking.firewall = {
|
|
||||||
enable = true;
|
|
||||||
allowedTCPPorts = [ 22 80 443 ];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
system.stateVersion = "22.05";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
{ ... }: {
|
|
||||||
services.nginx.virtualHosts."git.cloonar.com" = {
|
|
||||||
forceSSL = true;
|
|
||||||
enableACME = true;
|
|
||||||
acmeRoot = null;
|
|
||||||
locations."/" = {
|
|
||||||
proxyPass = "https://git.cloonar.com/";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
borg-passphrase: ENC[AES256_GCM,data:2WjoqMRmXvW9EGMmpMYhrC0Qt0Dk7QWlbEncZPdK2SxVljEoFibjVEr6jeYdAx6UkaXdjk9pD3PBbls2tWt0TiNQdh8=,iv:bHzASNjqqfPsQ/1w/oM7x0FubAzzRkn+iWrZlenU9rs=,tag:ektqi0rqEywg9YGybPQesw==,type:str]
|
|
||||||
borg-ssh-key: ENC[AES256_GCM,data:b/xZnUTfi85IG1s897CBF1HD7BTswQUatbotyZfLmbhxXxEyffUeaiGsT9Gh9yQqOKTstTihA48nVk/4ekAPD/ZGDQ189V1BwKkQ5chN9TSULofekfmemhUhVGjnx8OFl6hYYpTttQSTLHtczmfE2iX1JyrZy2Z+H+w6dbZjkYDayRUt/4+5wCtQJ1Nt7bjzwLWhjdVtwDeBLm/kCywVguZLCgyiuqmXMr1h9jpUS7URZegGz1lFs34Ismu1LtaRjFGRyd8aKaTU6PSxDbjE4dQ3Lh1Hm3nhtOrSkswBZLp8OTP6emrQ7c3oJp1zqO5zQHXxD2V5hkPw6ln0Ee1aQp1rvLD8shRXzRbHG+mySvjKLJvLypnNuYfQklqlnhbG+M1/NN13oVF13nHpKwP5q33sRr49mfHw8YHdRhHuhYHVrpy8ep0AmPXiDYCDM4cnlOMnzlH/toF0fq0YRny6QoqKNpaYhmA61MXRPTZCqoAcE1N+oo7HymjJetzL9b2FkPCoDOx989IJ8SUaBJpzR+agNsFi87htVllRp4ozms/m56dI0AdwqeAre00iMBzpVS0hXURE7fqvAnLHQD1goW9XB2mztqcJ09YafrOgTA3oyazWcAjxgV33GupxxIDmwRdLmavvr4qrHfddYctYLPI7VolqT9JmKN6iVG9vYsDutgoyRlhzbGASKPLgcYn9sGG+LBgTHfZyABnYOaUetVP72mhSN30ZZixcCskVlGg5C53wrW5o6mBv+PyG8PimxLmQylbvHUdGGVLQfMpJaaXgpUjBX1MWdQAVa+Nyjm7QwYdRKoCb3suQ6bOq5O9eotel3GPB8gpKzInhNA/0xiB4UyCGp1i21iRS9+Rc7yufo5s3t56k0643K2DhBUVgssiTsG15BbQdX4c1O28i9zwEZ+wVci1yvLX38M0a3tDDt9iW1BIOWehShS7dpyJR2/OgWLFagw9hYP5h24t5k6Gz2ODhPouaFccYDRUBR6UECxA+gDS+trN8iNSX1oWa0ys0XvgwWpJ2CrdSArNqe1BdhM47BQwudiA3RwaEN3wRh5PeykSk/3BUXK+ZdAr0BZ8ij2q4F8zQexLxnrV6xRqofNcVs62iJAjx6g86InSv0nNjLQ9U/fBTL66u1iRZFJhuxPjDNfLJZqT0TvRR7KBcNWTwTuMCGNp5s9TngMUF4uhHx8qGxtjfH58WjixOhC9lgUt7cYEFIeefcwIO9VVnKoiXK5sPIvIsjtLRzGvejYSd0ZwSF3Ly9FkWLkr+o5rs5bXtGMsSQ+BUFg5nM1BqrHIGv9M+F4kPxhnqm9/JXuMSQ+JUzix5N0vHuSTphCayDpMHJYRUEkDEmwPXMyB9zWVmvMb0ByUnfs/n/jmL4WRuggYqchIR3/xuco5HUqLbEKXiJ39wVgy+i3/biWOOEu5BmMx3qbgQ1+6nlxY+f1qpXZ8br0RlXLOQ6L/O9Qa9gKZaxLm/5GCiFZ+SeU/c5OgUndYqTk6FsbDlNurA69IqjwubG345lpdB9VPoGP7dLsx3VaGKW0bvr06oRaeasMx90SN5bGQJH+0iQFkGPhp0m2v31zpBk1IibXi5Qb1OWGXGYd+iNt1ZQF0HVuEqQEXI62x92QkaR7eHowR4tCRF1xH1ZrBkyjtdofUU2wPqsRrOWqGIZWUh/JpfXkSAZQo9yJKnHcp9d3BPEvWpLWS9g1Jfej5XG497aP6crWw5XawOyzi+PEgz2Y3Q0R/MM3S1W2R7Z+21nekbCfghpNylwIX4UYkeX8YorheiumkUfFXjktPSkFCTuUrYAA89WZjIIqd4/gt3tS7keCsjEiTkW2KdDPlzNItKnC8xWnpRc+Wh6ghA/nt3j4POb880j3scFoDjgOv5lNk2Q84S/IW+DQ3U8o4JrKiXsxchDvmgGbU4FbXZTGLXeM1CybmbZKogIHdwJkhC425oqA1PMiq5tDPLKpl2214JuaV4Xd8R0bwCSHYjQp9gqJT9j1Wg/3P0M3/VGZGoJEVriiBl6PBHP2CcvxK1NADDmMHgGQwwfROoSijAzzPKCy9sgzsquTkqzq8q4aChjGKShxs+52dpnmmuygSlxjyVQCEW9kLERf1Nm1arsLkHJ4ZsWgSrskGvjsPEvyEnpY33gGB7fpy90NW0GtELgGzEw/1nfLcFbRBJ7gH+4Dby2fBTxoV2ks9m0Fv6OWsfIe6H54zWLmqB1RkQaskb1wDKU3HATOmuYo/fByLIsMyR5l3P7LXWF5CJOprzp41rGts/ybJEG1EUtmVCs2epTwbeG/Waq1DB3TFa639ETjxOfGQ65PXp5aT1d5v+ko87LiR+0us6xwlfZ6NMRRZuPt4wycFgPUAAmpdmguwDKifHKA258g9kzotT25JeFFEMVhsMi1PoXEqA+sFomdsLt+Vtpr2aGMUWyHD/E2fgAtybLwxbjqDINi8vXWJxv/UZdH8wBOlWLtaeGg5/jRsMuL/hSSZ84Q2zfRVvV7/BZ7wnxfoXmAwRdTZijAvc9TxWszP6E5mAix7s/znU+1vnseJdxWa4Ff1wOGVL/Tem2K0J/mp75XuzSP7nCYDMgqhnvfzlD8vv6QpxtDUAbdTBDyPkQ4U9L6+y5ul5Aegpui+p0G9/0UHdBYhJiFd90omnhSmyHx2pvgUTfbL/Kv/pk7nwTv89a87NXNA9K6AATwx0kUPgIWs/5FGi8leCXGSsgBbJogL1htC72pKzVH6ckEzKeBzRADmwFLhnPIvp37ZkQPj0rrWRhkd5RqsFcN0166N+M4lPD0hzPd2+nEXDAOHoCK7U+BcRcJ3GUlyPU91dbWfo9otPd3naTvGVZuFDxOihLtBXaLTsxmS4STk6DVRjwNmX8YC9FwXkED19xEeH6KkaFs1nVXnmDqpvi2BcueT96t6TOeu5HcA9fAgFTpOKVT6cK2PcHTtJhjrPkfSYr0/ksJdV7r9N4JgAEfiASMMHS5uQWJlyJKWo92rJ2IvSCQx4lcK3gasgcTsVaYmuRORM+6263r4NKS8W8r55XvVyW/C7vvsVq6wF3xUkQadBkxIUQUVWxxCc1pWOlfWwMs0i+ZssoaWopbs7x45z86i+3HsHmfS6GuXUpQfgvXe9Bn7mOj7VQWaG9NIFUpIxisGfdY9L8+RXobo7etD3da7TNMs40BT+34tijcX53FzKwvG3ESNPB2hjOAITDta6LDOHhJrlVqn90p1DicThHOaT3fxt6ST287EhWqK9S1gpkLrp0gNSA9v+K9mBvWaWYNDXY7sGxOIMzCEIdFT18Pra92NhGTJtC0XizHDMUfGx5WAaard1Iy/PYXvavoAwp30qDCQGF+PgwSProa+JtQQPzoEgtSXNVhUWIzz10TACuo+vHt8sHvFG3VuU7jSOr9sqVrN36KMDUlwo0gavHKsjRxHf2OGh552q7AP+sM6Y5WhA4KhmQSUKCVxYVQ==,iv:U3+fjacm8+gZAjPQNz2mjFYTUbLyltTaPiSKb3lvCmk=,tag:ZR6zI1UijDayIvH3v35Hqg==,type:str]
|
|
||||||
zammad-key-base: ENC[AES256_GCM,data:HO9MuwcwjryuXr5No8sCPfso5bpLtQCoczrC/R214ecVIFwwH1uhMeNO8Tlh6EjRLPo7aVTSz87Vx5yaNVezvHCs55G6TT9mcNS/v/V7sbFz9dNIgbFblY3gFIAa4cViioYc71wdb7d4Tta7qhse5zQ41KhAqCWuGDgFErQA4Oc=,iv:b1wY8fW0psircSlNXwDjPzNWK8NyAMNqegitNcqV6U4=,tag:oQ7nyO9TKOOu6IF7ODzpPA==,type:str]
|
|
||||||
sops:
|
|
||||||
kms: []
|
|
||||||
gcp_kms: []
|
|
||||||
azure_kv: []
|
|
||||||
hc_vault: []
|
|
||||||
age:
|
|
||||||
- recipient: age16veg3fmvpfm7a89a9fc8dvvsxmsthlm70nfxqspr6t8vnf9wkcwsvdq38d
|
|
||||||
enc: |
|
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBoUWdTYlRjWDJvemF5Q2sr
|
|
||||||
VCtrS2dTTGRwUlNIWHd0WkVCRkRMcGhuTzE0ClNic1FmQ05UNWQwbGc4TUFMNGlI
|
|
||||||
K0RhK2pqUGY3UElmK1pNUEkxV2xGUTQKLS0tIFRORE9JTDRZK0MwZUJoc2xlcHFH
|
|
||||||
bmp3ZW14TVdCMHhkSi84NE5neDdrY3cKYfgu7aqvG6wQmEFhmzieXFGoQpyffPXj
|
|
||||||
jiHrAPjBBFy21wdYf0nQXNMzekqOMJwOj0oNA2b5omprPxjB9uns4Q==
|
|
||||||
-----END AGE ENCRYPTED FILE-----
|
|
||||||
- recipient: age1gjm4c3swt8u88e36gf2qlg3syxfc0ly94u64c42f2tsf24npw4csa6e4fw
|
|
||||||
enc: |
|
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBUUjQxWnBMQXo3QmF1STUw
|
|
||||||
bHh1NDhvQXZIQ2RiOUx5OU5Wc3BVSEJDUEZVCmVzeFk5SWpMbVV4VUdsRmhiaWwz
|
|
||||||
bTJDY1pJRXJvNUdCSXJqQ3Byd3lWN2sKLS0tIHRKdXRNc1BYcURBRVNlenk1OEl3
|
|
||||||
Q05BN0VnQ0haeHBobWhRV0EzL3dLSEkKWlALiX5mvG8y0WUc8yFWMbcpSRrSGoQx
|
|
||||||
SHaOlDCjYvViZ7GPRLqnSwDGZ1clC6JsTbwKXrMsWdZBKvSO/VIWQw==
|
|
||||||
-----END AGE ENCRYPTED FILE-----
|
|
||||||
lastmodified: "2024-08-16T11:12:23Z"
|
|
||||||
mac: ENC[AES256_GCM,data:nMLxD/WP3LxLTECQ/wQjiDW3F2Lx8yeMTkNIg97eipebVZwTLiVGg4t+sVzen+X3t4tPixO2a72mWMtIVQKs8d2MzkydLh+LjYItUBP+uw/rnCjB0zfxiPN883+FO6q4+BoT0JJc4LUHbgQQWEDnKaqld4/ICE1xJbPZVEJWo40=,iv:JenHaRqB8ZVDRV5rUOgMURflqQzfOrt9pHege2oiT7g=,tag:xv0p2oW1P0FPqcrRoQ/6tw==,type:str]
|
|
||||||
pgp: []
|
|
||||||
unencrypted_suffix: _unencrypted
|
|
||||||
version: 3.8.1
|
|
||||||
@@ -1,120 +0,0 @@
|
|||||||
{ config, pkgs, ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
services.zammad = {
|
|
||||||
enable = true;
|
|
||||||
port = 3010;
|
|
||||||
secretKeyBaseFile = config.sops.secrets.zammad-key-base.path;
|
|
||||||
database = {
|
|
||||||
createLocally = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
services.nginx.enable = true;
|
|
||||||
services.nginx.virtualHosts."support.cloonar.com" = {
|
|
||||||
forceSSL = true;
|
|
||||||
enableACME = true;
|
|
||||||
acmeRoot = null;
|
|
||||||
|
|
||||||
extraConfig = ''
|
|
||||||
# Virtual endpoint created by nginx to forward auth requests.
|
|
||||||
location /authelia {
|
|
||||||
internal;
|
|
||||||
set $upstream_authelia https://auth.cloonar.com/api/verify;
|
|
||||||
proxy_pass_request_body off;
|
|
||||||
proxy_pass $upstream_authelia;
|
|
||||||
proxy_set_header Content-Length "";
|
|
||||||
|
|
||||||
# Timeout if the real server is dead
|
|
||||||
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
|
|
||||||
|
|
||||||
# [REQUIRED] Needed by Authelia to check authorizations of the resource.
|
|
||||||
# Provide either X-Original-URL and X-Forwarded-Proto or
|
|
||||||
# X-Forwarded-Proto, X-Forwarded-Host and X-Forwarded-Uri or both.
|
|
||||||
# Those headers will be used by Authelia to deduce the target url of the user.
|
|
||||||
# Basic Proxy Config
|
|
||||||
client_body_buffer_size 128k;
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_set_header X-Forwarded-Host $http_host;
|
|
||||||
proxy_set_header X-Forwarded-Uri $request_uri;
|
|
||||||
proxy_set_header X-Forwarded-Ssl on;
|
|
||||||
proxy_redirect http:// $scheme://;
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
proxy_set_header Connection "";
|
|
||||||
proxy_cache_bypass $cookie_session;
|
|
||||||
proxy_no_cache $cookie_session;
|
|
||||||
proxy_buffers 4 32k;
|
|
||||||
|
|
||||||
# Advanced Proxy Config
|
|
||||||
send_timeout 5m;
|
|
||||||
proxy_read_timeout 240;
|
|
||||||
proxy_send_timeout 240;
|
|
||||||
proxy_connect_timeout 240;
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
|
|
||||||
locations."/" = {
|
|
||||||
proxyPass = "http://127.0.0.1:3010";
|
|
||||||
proxyWebsockets = true;
|
|
||||||
extraConfig =
|
|
||||||
"proxy_set_header X-Forwarded-Proto 'https';" +
|
|
||||||
"proxy_set_header X-Forwarded-Ssl on;" +
|
|
||||||
"proxy_connect_timeout 300;" +
|
|
||||||
"proxy_send_timeout 300;" +
|
|
||||||
"proxy_read_timeout 300;" +
|
|
||||||
"send_timeout 300;"
|
|
||||||
;
|
|
||||||
};
|
|
||||||
locations."/auth/sso" = {
|
|
||||||
proxyPass = "http://127.0.0.1:3010";
|
|
||||||
proxyWebsockets = true;
|
|
||||||
|
|
||||||
extraConfig = ''
|
|
||||||
# Basic Authelia Config
|
|
||||||
# Send a subsequent request to Authelia to verify if the user is authenticated
|
|
||||||
# and has the right permissions to access the resource.
|
|
||||||
auth_request /authelia;
|
|
||||||
# Set the `target_url` variable based on the request. It will be used to build the portal
|
|
||||||
# URL with the correct redirection parameter.
|
|
||||||
auth_request_set $target_url $scheme://$http_host$request_uri;
|
|
||||||
# Set the X-Forwarded-User and X-Forwarded-Groups with the headers
|
|
||||||
# returned by Authelia for the backends which can consume them.
|
|
||||||
# This is not safe, as the backend must make sure that they come from the
|
|
||||||
# proxy. In the future, it's gonna be safe to just use OAuth.
|
|
||||||
auth_request_set $user $upstream_http_remote_user;
|
|
||||||
auth_request_set $groups $upstream_http_remote_groups;
|
|
||||||
auth_request_set $name $upstream_http_remote_name;
|
|
||||||
auth_request_set $email $upstream_http_remote_email;
|
|
||||||
proxy_set_header Remote-User $user;
|
|
||||||
proxy_set_header Remote-Groups $groups;
|
|
||||||
proxy_set_header Remote-Name $name;
|
|
||||||
proxy_set_header Remote-Email $email;
|
|
||||||
# If Authelia returns 401, then nginx redirects the user to the login portal.
|
|
||||||
# If it returns 200, then the request pass through to the backend.
|
|
||||||
# For other type of errors, nginx will handle them as usual.
|
|
||||||
error_page 401 =302 https://auth.cloonar.com/?rd=$target_url;
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
locations."/ws" = {
|
|
||||||
proxyPass = "http://127.0.0.1:6042";
|
|
||||||
proxyWebsockets = true;
|
|
||||||
extraConfig =
|
|
||||||
"proxy_set_header X-Forwarded-Proto 'https';" +
|
|
||||||
"proxy_set_header X-Forwarded-Ssl on;" +
|
|
||||||
"proxy_read_timeout 86400;" +
|
|
||||||
"send_timeout 300;"
|
|
||||||
;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
sops.secrets = {
|
|
||||||
zammad-key-base.owner = "zammad";
|
|
||||||
};
|
|
||||||
|
|
||||||
services.postgresqlBackup.enable = true;
|
|
||||||
services.postgresqlBackup.databases = [ "zammad" ];
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,51 +0,0 @@
|
|||||||
# args of buildLinux:
|
|
||||||
# https://github.com/NixOS/nixpkgs/blob/nixos-unstable/pkgs/os-specific/linux/kernel/generic.nix
|
|
||||||
# Note that this method will use the deconfig in source tree,
|
|
||||||
# commbined the common configuration defined in pkgs/os-specific/linux/kernel/common-config.nix, which is suitable for a NixOS system.
|
|
||||||
# but it't not suitable for embedded systems, so we comment it out.
|
|
||||||
# ================================================================
|
|
||||||
# If you already have a generated configuration file, you can build a kernel that uses it with pkgs.linuxManualConfig
|
|
||||||
# The difference between deconfig and the generated configuration file is that the generated configuration file is more complete,
|
|
||||||
#
|
|
||||||
{
|
|
||||||
fetchFromGitHub,
|
|
||||||
linuxManualConfig,
|
|
||||||
ubootTools,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
(linuxManualConfig rec {
|
|
||||||
modDirVersion = "6.1.43";
|
|
||||||
# modDirVersion = "5.10.65";
|
|
||||||
version = "${modDirVersion}-xunlong-rk3588";
|
|
||||||
extraMeta.branch = "6.1";
|
|
||||||
# extraMeta.branch = "5.10";
|
|
||||||
|
|
||||||
# https://github.com/orangepi-xunlong/linux-orangepi/tree/orange-pi-6.1-rk35xx
|
|
||||||
src = fetchFromGitHub {
|
|
||||||
owner = "orangepi-xunlong";
|
|
||||||
repo = "linux-orangepi";
|
|
||||||
# rev = "122b41d84d018af909a766e48f3f90cbea9868e0";
|
|
||||||
# hash = "sha256-kOhxDP1hbrrIriOXizgZoB0I+3/JWOPcOCdNeXcPJV0=";
|
|
||||||
# rev = "eb1c681e5184e51d8ce1f351559d149d17f48b57";
|
|
||||||
# hash = "sha256-kOhxDP1hbrrIriOXizgZoB0I+3/JWOPcOCdNeXcPJV0=";
|
|
||||||
rev = "752c0d0a12fdce201da45852287b48382caa8c0f";
|
|
||||||
hash = "sha256-tVu/3SF/+s+Z6ytKvuY+ZwqsXUlm40yOZ/O5kfNfUYc=";
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Steps to the generated kernel config file
|
|
||||||
# 1. git clone --depth 1 https://github.com/armbian/linux-rockchip.git -b rk-6.1-rkr1
|
|
||||||
# 2. put https://github.com/armbian/build/blob/main/config/kernel/linux-rk35xx-vendor.config to linux-rockchip/arch/arm64/configs/rk35xx_vendor_defconfig
|
|
||||||
# 3. run `nix develop .#fhsEnv` in this project to enter the fhs test environment defined here.
|
|
||||||
# 4. `cd linux-rockchip` and `make rk35xx_vendor_defconfig` to configure the kernel.
|
|
||||||
# 5. Then use `make menuconfig` in kernel's root directory to view and customize the kernel(like enable/disable rknpu, rkflash, ACPI(for UEFI) etc).
|
|
||||||
# 6. copy the generated .config to ./pkgs/kernel/rk35xx_vendor_config and commit it.
|
|
||||||
#
|
|
||||||
configfile = ./rk35xx_vendor_config;
|
|
||||||
allowImportFromDerivation = true;
|
|
||||||
})
|
|
||||||
.overrideAttrs (old: {
|
|
||||||
name = "k"; # dodge uboot length limits
|
|
||||||
# nativeBuildInputs = old.nativeBuildInputs ++ [ubootTools];
|
|
||||||
})
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
{
|
|
||||||
stdenv,
|
|
||||||
fetchurl,
|
|
||||||
}:
|
|
||||||
stdenv.mkDerivation {
|
|
||||||
pname = "mali-g610-firmware";
|
|
||||||
version = "g21p0-01eac0";
|
|
||||||
|
|
||||||
src = fetchurl {
|
|
||||||
url = "https://github.com/JeffyCN/mirrors/raw/e08ced3e0235b25a7ba2a3aeefd0e2fcbd434b68/firmware/g610/mali_csffw.bin";
|
|
||||||
hash = "sha256-jnyCGlXKHDRcx59hJDYW3SX8NbgfCQlG8wKIbWdxLfU=";
|
|
||||||
};
|
|
||||||
|
|
||||||
buildCommand = ''
|
|
||||||
install -Dm444 $src $out/lib/firmware/mali_csffw.bin
|
|
||||||
'';
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
{ fetchFromGitHub, stdenvNoCC, ... }: stdenvNoCC.mkDerivation {
|
|
||||||
pname = "orangepi-firmware";
|
|
||||||
version = "2024.01.24";
|
|
||||||
dontBuild = true;
|
|
||||||
dontFixup = true;
|
|
||||||
compressFirmware = false;
|
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
|
||||||
owner = "orangepi-xunlong";
|
|
||||||
repo = "firmware";
|
|
||||||
rev = "76ead17a1770459560042a9a7c43fe615bbce5e7";
|
|
||||||
hash = "sha256-mltaup92LTGbuCXeGTMdoFloX3vZRbaUFVbh6lwveFs=";
|
|
||||||
};
|
|
||||||
|
|
||||||
installPhase = ''
|
|
||||||
runHook preInstall
|
|
||||||
|
|
||||||
mkdir -p $out/lib/firmware
|
|
||||||
cp -a * $out/lib/firmware/
|
|
||||||
|
|
||||||
runHook postInstall
|
|
||||||
'';
|
|
||||||
}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
borg-passphrase: ENC[AES256_GCM,data:jHb+yXK0RqNdVYtWiueztZFlHC/xQ6ZiAOUcLt6BxmZQewuL3mh4AZ+lQdmA/4EaaTTIhVMR3xFx5fU6b2CtNLiGb/0=,iv:IW09B1EE1OupMCOvv13MXRYiMsD4VmIfyYONUyrPX1c=,tag:3ankeLOaDJkwRUGCd72DuA==,type:str]
|
|
||||||
borg-ssh-key: ENC[AES256_GCM,data:ir25XfzLBb/H/YWzxP501hCaLBB4jpiLW7WUcnvguzosT9QeOtBdJ0WB1IndEMtiEgQyE9kyGOJ3QJwzbQNkX6CG96Uzt2mKw8gw8ayUqC+B9zR8eIRYiDKOYs+YREVo7nA5pLLzIc/9jaRicDFMmw1Thmk7UUJKB1DNV49nU9K+nAfrCzk7ZQieY8oaasFD0cvNb4Ndj6f9PWSXkNBwKK52ig4hDeNBs1bdy8nDE8VqlwOo8H2DcYMzdMjKCZDBRccy8NofHEhakCW5OdliFyIHsLkcBHca3Bp46JN7wbo8avPPd9bXGuRiOSWYq50RcyZUovnB3g7Dk3swCyuiFztnStN63+g7ZnGFdYLYDYfuDSPN1W2HCkknmaoT910VNE8sEAMyfXk4tqJv4eW4qmFk2UwPlRCrsk9GtdRQ5wm8muNPHEZ8s2dGkn4WDcjy7SUpgF4UJJZV8iJe74W9BK1Ef+AWWNsNjYfZde3iw1+8Fz1u65u4seFWqQMok/noADpszbpk+YYRoM+5D/YVMx+KeDtoFqnZfULM/BqvAqdYYZtRzojndeNW6Ea4sxDE+XQ5b1OwGFlNAlnuS1fYYPvKojrKNgT9KMwbsvPijU5vFddY8Qpz2h6GKEv/OW87j5UeyDW4l32lvyawBuzczBfiFgCElggGSZHM5rjE4Deb06eQleTioZ79EDXTv5UsPQ6Bc1v5Wvnu8DvxJe4B10vxH70JIGIlmjwo0yhMkxDTN7BkAGQC0QAPhwtURDq+XVufQNjlTUjjH1Q1E4u0Vy19clMs8SStqFeMN02BfWZdS9mbueF5Ehc+8wTfAs43CQFublJ4wfG1PzEbqj9LZdimFe4hCnE2y6Gbf591shugVSAMA3UXQUuvFQmm69i9gz88YSYrkLlVStM+dtXCugZho72xgHtnI+5o19wuoZPRoxe47W0T2kJZZeomtqoAsSo5yr5JeYzYdaHYcK2fgRY0HWgWzOxnVEfX/gRPR3b20Tko6yp9lIDECkXVDQSxptxqIYk+VuETnD9YF2OpYeHZLGoo9OLdEHVZRcuy1S74aAOJGO9SAHLw3eukxG//AZlwcOYjOsYDVt3BjhYZEkYCLg8GkAqV/7bGsxT7pgckNEB2NRYQI9ckqEcEw9CdkYre67HwfPCvAble68VnRzgp+v5s0koVjTURF9FTxvVOXQEbvSpY828idyx6nOaAIHoqpIOFz4jsGE9L4FKamqnlnjzj2Ri/MboT9JQBj8bnIF/ej+dQGpfqZo7zqtu3d0B/9e0xuVTcqI9Bxlqn3D4108I8R37Ctr5OFKloeOZ8HHMsHcBUAzZC6/fWrOspru14YHW2YNj8nBxHve/P3oiTQ/nlXLcBGLoFfI+hOpofccQB8FnkKfTbLSRUGrGY6NJt9RCnZgm2+RUgel77XpsCsT/Q5ZGclBdyk8mSaqVjiNyHCbCV5tF/tWnuvf859S0tcmqbJ0FhIRAvwxFucmfi6FSPX5HEMdRbNV7szrHKSX60u7YA2DBBzv3c/+C2bxq70vhwFelqz7FqpVKwebbE4/a59lZpibzefCoji/TPDJB62/ox5NHHE5qenv7IPcEj3dEmdasbrApAw1UFsFlRCnlg4JIYley/AQx7OzUSImqkG8JWvSJ4JXijhsr9dPFR/cb0srUO88aFNh/ZUQhELZCVnzAsF81Y4w6LTGApMfUVN/yx9MqENGvObywzMls1UJphvzDZzvb+Ue6eqELogN1QcEI/WOirwVtJO6E7IevEtK4xxWsLfRHVjtbLc4QjCWuiyszAPTTttKJ+iC2h14Wj1XoiMpWRiVnj+jI9iWRen96P4glYEfuCYQS6vbGkNDEoZt/FnkLJDbLdjXatmhUoRpvExOtp26ULR/f1lwzLMJBt1qPvhuGur1ru2B1e8+AVte1Cfjmk+xrnxNwkTFLGe89Qjd77wPyQv9h0YrhZ6uDi2zLemhZs2LjW5ZvzV5P4thMDxkhezJHatPHAGa8OfclJOyrRTyW2azdz2A45MNzZtCQcnQdQxBXf+XRskLnhquZfgv66hFITjuF/HeI9cq4HJcrgaOcVj+tBdK1bTCyL2kqKkCpSCbh/Pv6FuAlDXgLjsWwZgOKz8gfTIfXMapPLDYVTbS/PPPABylZflN98FFyeFDHB3Fwn1a6qAJ0mC7+4sowVZ1DIAoflaHqNs5TXyb3KeZGgXj5ZQwhv1z6NySvOS6cHxx0PvkFo99T1NHztxCRERNvBdWSwsr32DTwEvZo5iNPy3lvKI5A+rXc7jlQkUbufbddtLw2iPtt29XyMDOysK010fXzzQRjaz4R8ZaDtHNjqPrynvqFPXRB0VSIrwXS2utU7bmD+0dGX26t9k5qRBi7Gm+iZNKGMnSRsm17bVk5o8q0tb1P1eGL9mexZJJvxolfXVFJJtR8m6vLmUX1LSht/JhoWFElrINl0hviwd1dehmTqdQqWz5/imjF+pVOasrt7XVZ+7T/rDpuwNl375qSZptM1pMUExJ3CvzigpnarXXQxEBYkf0haGvQwPWNVHe/bR/1VooSQkH/mGg1g+rcTqp4yB5hsFu1lNK4ph04WQOqaafg40HBv6e5cOjLkFdEtYNpjyd6sRS+WHk7zzFlfPVlzijq8f+oDH9ALRzNnL1Y2DrX53wx4dBBWvxE1Yhb6Kj6Er4ZDiRLLXo+wJOGCpnNTPJMVaYskZ+LN2e9nS2/ZwbsNBnPHxSqCc1oP4d3yXH0j90VKnWg79aIEOagRvTF/9F6SkkGL9zVuUnoVSPwq97etWWtjGoEORMGY7jkGOK+U391p7Z69Hrv2AejS1BoSDeGcxXasFvINpmc+Hl2c+zOlFBySu2zA39cVlcStUFICA5GCmE5Eum4ED9DXP6RAuicD7YE0qSKbMkfLxIWMCZ6wBcwVUjdt43SI/ZqdpDm3E1kTRg07dE0R091rtfzEiIwBM4xFPJBafOx0L/Do61YMOHGzi6wgIQO7P7wIslv62M8MD1KKa/eH0tE2vhG/GyEGtKkg3P9vZRJwioifyshS1hvrt5pLinuCaDYyqMAl8Ro0OOm8di7+mBvXib0nRLfW7wBGDA4ADTipizNWAmbspQQl89kH5gdxgXO5U+N/qc0zXbpB+qeHVkPIK1DmrJ8pHLOE8mOpLy7eHUsSku/WtTt/RP4pcDbBU/43MCbk7NXKu/LjKjkQBjAL49LxnYmhEU7X//jtwSPE3gdx0x+wRJxzlbehM6rpfDRV5WQGSFf7yjLc/Ga1KwsgVdAstJEzDdv2vWSsjNzfJvHVBLrQPIC9fggi3DeLiHTAryCUcLUhNj4xtZWhSS1qmx07E4VzfjDJLMOsLY0vlimgngZ3YYCjC3Sw0frfQH2SZvmbLd3XfBdud67ZaMUobcRhnKzQnilldyD1jWVWLdVTup4RVxT4GYek9nmYflzpWWmwbXatz9Sgcw==,iv:9E1uiPqM3Hh4KWtL8haxm6PRm2VPc+DggrA135FvfB8=,tag:QSOgzVH9IBMgZxJvUhvY2w==,type:str]
|
|
||||||
ddclient: ENC[AES256_GCM,data:EaXjXS/bwL3S/Fr+rzQ7dXA1eIzeFpHH7H+SvoNhVSg=,iv:3BzjnJG5yT1W8ob2nm0oUlr+sSJ73W/ctl48xyxeeWM=,tag:TqKSwfxF0V1v5T8VT/qblw==,type:str]
|
|
||||||
wrwks_vpn_key: ENC[AES256_GCM,data:gGipXC8JJO59b4KWMSo0+r761raQl7RzgBuUbXmPEKlZR21bs5XRAQalzDCFNtjcpNkXiGqAHCLkDTtjPagMsw==,iv:MH1EBJEOdQDEgm9E0F884fynhsH8KiS5QSc605XbASQ=,tag:FUM1eptHS0rpt6ILyQjGOg==,type:str]
|
|
||||||
wg_cloonar_key: ENC[AES256_GCM,data:Dtp6I5J0jU5LLVwEFU4DFCpUngPRmFMebGXnk2oSwsKtsir/DtRBFG7ictM=,iv:1Abx/EAZRJrRQURljofzUYDgJpuREriX0nSrFbH5Npw=,tag:l4uFl9Uc+W0XeLVfLGmgZA==,type:str]
|
|
||||||
wg_epicenter_works_key: ENC[AES256_GCM,data:LeLjfwfaz+loWyHYRgIMIPzHzlOnhl9tluKcQFgdes6r+deft1JfnUzDuF0=,iv:DKrc3I+U2hWDH8nnc8ZQeaVtA1eVXu7SXdTn1fxHoH4=,tag:V0PL0GrL2NEPVslAZa801A==,type:str]
|
|
||||||
wg_epicenter_works_psk: ENC[AES256_GCM,data:Den3NDWdP013Or6/2Vll1igUahuRSNW4hu+nDa5vkr93bbveQTaWFT4TD4U=,iv:r3UsD3+3lUIP2X3Grti7wpXTQBXtu1/MdrycEmpZfsI=,tag:ghbAcxmjGVOe9jCZsmFzjA==,type:str]
|
|
||||||
wg_ghetto_at_key: ENC[AES256_GCM,data:OIHmoy3SpIi9aefZnZ1PzpyHbEso18ceoTULf2eQkx1rJbaxC6PD1lma7eQ=,iv:u0eFjHHOBzPTmBvBEQsYY5flcBayiAQKd6e7RyiPwJI=,tag:731C9wvv8bA5fuuQq+weVQ==,type:str]
|
|
||||||
gitea-runner: ENC[AES256_GCM,data:IRx9QzbLJrkF/DYvpVf2012BiSBnHZJe10opkRO2kJuegdb0denW3mvmnU4isoj7jO/0QyN6HZHlHb5ihC7fFl4LavPDVjAAhZPynkpDw9IHFeqZDUSPzxQsq7FibKmfEpEmWEz+Npe8JI1kl694XYV/kqErKa3JrZS7Jm8zFcv7DSY/V5bdy4Is8ZSRtHiP/aVzFdsvjwtissCDnCl7zRZjXUcN0FssvPHBZHxLuc68EoagIw1aVSzkvSVBXer4rFdlefjskFelRnUr3pvm188=,iv:VnvPFDFGz/QyfQmZxQFB3J2ReqaHdRaypb2Vnq7Dthw=,tag:19rx0nlmXLj/6yPRAFGigA==,type:str]
|
|
||||||
gitea-runner-token: ENC[AES256_GCM,data:Nd0vsnuJficsdZaqeBZXa9vD7PLMdDtV9sMX0TxUSEMNU7Reu3HLCWuvP0easPU=,iv:4mrfQc1tobg/QiExUuWST6iU9TdNwiS1BMmOnQqCFZU=,tag:85aRoD3IkRq3mcoPdLKaBQ==,type:str]
|
|
||||||
drone: ENC[AES256_GCM,data:S8WTZqGHfcdpSojavZ87GdE5dagcTAdHBVQEbHHgnB4V7aczS6c5QdEJxK920Pjpf6o54OOQYniVsPiiXSxwjExDKPzhs/DG2hfigmf8RgfkP+3tF2W0KiPmV2jxog8w226ZKnI+hSBs8tuIfJBhrpY7Y/YNmTPfq+cnnLS8ibYqytcpzoogI9I8THzHCu3r+yejoGSyTMs9L4gPhOjz5aK4UV6V,iv:zqN/aSBI3xGGNDnpHPGyQnQP2YZOGUk6dAGtON/QlHU=,tag:o9YFDKAB5uR9lPmChyxB8g==,type:str]
|
|
||||||
home-assistant-ldap: ENC[AES256_GCM,data:uZEPbSnkgQYSd8ev6FD8TRHWWr+vusadtMcvP7KKL2AZAV0h1hga5fODN6I5u0DNL9hq2pNM+FwU0E/svWLRww==,iv:IhmUgSu34NaAY+kUZehx40uymydUYYAyte1aGqQ33/8=,tag:BKFCJPr7Vz4EG78ry/ZD7g==,type:str]
|
|
||||||
home-assistant-secrets.yaml: ENC[AES256_GCM,data:m7uOVo7hPk/RmqqRS6y7NKoMKsR9Bdi1ntatsZdDOAbJMjZmZL2FgPEHi/zF73zCfRfTOca3dwpulR3WXZ9Ic1sbUIggmusJMg4Gellw1CUhx7SbQN5nieAbPbB9GVxMuV4OakD1u7Swz8JggDT6IwojSnuD5omCRCyUH1wvKB+Re59q6EStderlm5MJNVFlVrbKVbLKLcw4yRgTh34BGnTTjcJmgSlQjO1ciu2B7YQmdl0Fw6d8AdbEzgB5TFG5ONc85UhJDE8Wlw==,iv:GCtpcVChN2UMWtfnWURozCfVj2YbRPqp/bH4Jjntybs=,tag:pcxP7gTBtXMNT5iyW5YXTw==,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]
|
|
||||||
firefox-sync: ENC[AES256_GCM,data:uAJAdyKAuXRuqCFl8742vIejU5RnAPpUxUFCC0s0QeXZR5oH2YOrDh+3vKUmckW4V1cIhSHoe+4+I4HuU5E73DDrJThfIzBEw+spo4HXwZf5KBtu3ujgX6/fSTlPWV7pEsDDsZ0y6ziKPADBDym8yEk0bU9nRedvTBUhVryo3aolzF/c+gJvdeDvKUYa8+8=,iv:yuvE4KG7z7Rp9ZNlLiJ2rh0keed3DuvrELzsfJu4+bs=,tag:HFo1A53Eva31NJ8fRE7TlA==,type:str]
|
|
||||||
sops:
|
|
||||||
kms: []
|
|
||||||
gcp_kms: []
|
|
||||||
azure_kv: []
|
|
||||||
hc_vault: []
|
|
||||||
age:
|
|
||||||
- recipient: age14grjcxaq4h55yfnjxvnqhtswxhj9sfdcvyas4lwvpa8py27pjy2sv3g6v7
|
|
||||||
enc: |
|
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB6aEpEZklTYi9oakF6WTg4
|
|
||||||
RDlNV1FrWlN6Skd1V1BmRU93SGJ1RTNGc2xRCmlzRk56NnRrbkthcWhpTjNlb0VV
|
|
||||||
cE9GaU5TRjAxaGFYTlkzbGtQY092eUkKLS0tIGdncHpVdTd5ZDN0NzllVmFuN2pR
|
|
||||||
WDJzNzZKdGxzOTRBZ1BPRUgxSE5DQ1EK3t2074FilJxZDQYZew8ckEbaBnQrDOsW
|
|
||||||
f+G4AnR83inhGsJwebmwwyI5dORVuBldA0CNjvihAmhlvf7G4TZ/Vw==
|
|
||||||
-----END AGE ENCRYPTED FILE-----
|
|
||||||
- recipient: age16veg3fmvpfm7a89a9fc8dvvsxmsthlm70nfxqspr6t8vnf9wkcwsvdq38d
|
|
||||||
enc: |
|
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB6MVNyWE0zd1FScmpOcVNs
|
|
||||||
R2FsWGxyZ0ZiZzkrNjEyNkVybjlVbFh6WFVFCmtoWFd2bTRFUU8zL3J1Ry9uak56
|
|
||||||
ZUxKMVdha1h1ajBnb1grbTNPcjkrc3cKLS0tIHZXL25UU2Fqd2VVL0ZhNE1vVUVJ
|
|
||||||
TWtVdzIwNU1McDNtM3VMdjhZNmhENGsK1x5pbkUdFuZtxLPLHQonmJEwSlWYBwjv
|
|
||||||
50v5i8fK4CTSjKO3VLh6iCkFUq2RYwerCpK2PdrujH33ymSUOzlXWw==
|
|
||||||
-----END AGE ENCRYPTED FILE-----
|
|
||||||
- recipient: age1v6p8dan2t3w9h94fz4flldl32082j3s9x6zqq7u5j66keth9aphsd6pvch
|
|
||||||
enc: |
|
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB1R3V0Z3ZxQSt4dnkyNS96
|
|
||||||
VGRqWUV6WllLenY2TWF2OTVWbEdUY2NDbFNvCmpwV3dwS2hwbk8zV0ZsMDYycHky
|
|
||||||
bU8zRjY1aFF2T0l3YzBaQ0l1UDFRYjAKLS0tIEgwbzF3TytRNHduYkErSTI3WXJF
|
|
||||||
STZ2NnlKaDdLeCt3RS9IRnc5dUkzZmsK5VwTv1CASmuvEvVLd67YIFx2fouXONtA
|
|
||||||
vtuVW1MCG4Z/btsQ5smRUsKWVdL+G2Cy1dk8SWZcy1tK3bDOLZ/VNg==
|
|
||||||
-----END AGE ENCRYPTED FILE-----
|
|
||||||
- recipient: age12msc2c6drsaw0yk2hjlaw0q0lyq0emjx5e8rq7qc7ql689k593kqfmhss2
|
|
||||||
enc: |
|
|
||||||
-----BEGIN AGE ENCRYPTED FILE-----
|
|
||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBLRXBDdXhYL01jaDRkbXZP
|
|
||||||
R2hFOXpBT25CRXNvTjhoNU1JWDRpa2RlcW1zCjlBMlZabFZhMTI1U1FxalI5SlBS
|
|
||||||
SkVMVXBldHF1aUdBREFyckpYVVBzaE0KLS0tIGowV3oxU0FYRjNoTDB3SWFMZWVF
|
|
||||||
bVBNM0o0KzJRUndkSlZzeUQ2UU91N28KFfW9ID6X0IPeCnRBc6v7EGJAZ7my70Ih
|
|
||||||
wHMDCrsnvs1XUFlHCFq4a7fzbqMcBoZ3Gkq5gBeuL2Cmuqoh92slzA==
|
|
||||||
-----END AGE ENCRYPTED FILE-----
|
|
||||||
lastmodified: "2024-08-02T22:57:14Z"
|
|
||||||
mac: ENC[AES256_GCM,data:U9/pKXdqXMvjQgyTIGz0JG+88aBXVgp29Fmm0OE66KMArkX8ungcEtdnGYKhD0gFJKLrKZZY5V8oyAXEq95D+Bh8ZnfmQibYw04cPldc6kTZstsrpbzrWVfn6sqG/ih12oXdsLws+H6IeN+O2qGZHDIVjvPufAdJ3A2X+Yakahg=,iv:mG+dGv3l/PNhggvlujLxDGU5z47qVA9sOTUbU2b2dPo=,tag:Rz2av33iwa9aYR7c0cviEg==,type:str]
|
|
||||||
pgp: []
|
|
||||||
unencrypted_suffix: _unencrypted
|
|
||||||
version: 3.8.1
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
https://channels.nixos.org/nixos-24.05
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
{ ... }: {
|
|
||||||
services.avahi = {
|
|
||||||
enable = true;
|
|
||||||
reflector = true;
|
|
||||||
allowInterfaces = [
|
|
||||||
"server"
|
|
||||||
"lan"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
{ config, ... }:
|
|
||||||
{
|
|
||||||
services.ddclient = {
|
|
||||||
enable = true;
|
|
||||||
use = "if, if=wan";
|
|
||||||
protocol = "hetzner";
|
|
||||||
# server = "https://dns.hetzner.com/api/v1/";
|
|
||||||
username = "dominik.polakovics@cloonar.com";
|
|
||||||
passwordFile = config.sops.secrets.ddclient.path;
|
|
||||||
zone = "cloonar.com";
|
|
||||||
domains = [
|
|
||||||
"fw.cloonar.com"
|
|
||||||
"vpn.cloonar.com"
|
|
||||||
"git.cloonar.com"
|
|
||||||
"palworld.cloonar.com"
|
|
||||||
"matrix.cloonar.com"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
sops.secrets.ddclient = {
|
|
||||||
# owner = config.systemd.services.ddclient.serviceConfig.User;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
{ config, pkgs, ... }: {
|
|
||||||
virtualisation = {
|
|
||||||
oci-containers.containers = {
|
|
||||||
deconz = {
|
|
||||||
autoStart = false;
|
|
||||||
image = "marthoc/deconz";
|
|
||||||
volumes = [
|
|
||||||
"/etc/localtime:/etc/localtime:ro"
|
|
||||||
"/var/lib/deconz:/root/.local/share/dresden-elektronik/deCONZ"
|
|
||||||
];
|
|
||||||
environment = {
|
|
||||||
DECONZ_DEVICE = "/dev/ttyACM0";
|
|
||||||
TZ = "Europe/Vienna";
|
|
||||||
};
|
|
||||||
extraOptions = [
|
|
||||||
"--network=server"
|
|
||||||
"--ip=10.42.97.22"
|
|
||||||
"--device=/dev/ttyACM0"
|
|
||||||
"--hostname=deconz"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,381 +0,0 @@
|
|||||||
{ ... }: {
|
|
||||||
services.kea.dhcp4 = {
|
|
||||||
enable = true;
|
|
||||||
settings = {
|
|
||||||
interfaces-config = {
|
|
||||||
interfaces = [
|
|
||||||
"lan"
|
|
||||||
"server"
|
|
||||||
"infrastructure"
|
|
||||||
"multimedia"
|
|
||||||
"smart"
|
|
||||||
"guest"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
lease-database = {
|
|
||||||
name = "/var/lib/kea/dhcp4.leases";
|
|
||||||
persist = true;
|
|
||||||
type = "memfile";
|
|
||||||
};
|
|
||||||
rebind-timer = 2000;
|
|
||||||
renew-timer = 1000;
|
|
||||||
subnet4 = [
|
|
||||||
{
|
|
||||||
pools = [
|
|
||||||
{
|
|
||||||
pool = "10.42.96.100 - 10.42.96.240";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
subnet = "10.42.96.0/24";
|
|
||||||
interface = "lan";
|
|
||||||
option-data = [
|
|
||||||
{
|
|
||||||
name = "routers";
|
|
||||||
data = "10.42.96.1";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "domain-name";
|
|
||||||
data = "cloonar.com";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "domain-search";
|
|
||||||
data = "cloonar.com";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "domain-name-servers";
|
|
||||||
data = "10.42.96.1";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
reservations = [
|
|
||||||
{
|
|
||||||
hw-address = "04:7c:16:d5:63:5e";
|
|
||||||
ip-address = "10.42.96.5";
|
|
||||||
server-hostname = "omada.cloonar.com";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "30:05:5c:56:62:37";
|
|
||||||
ip-address = "10.42.96.100";
|
|
||||||
server-hostname = "brn30055c566237.cloonar.com";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
pools = [
|
|
||||||
{
|
|
||||||
pool = "10.42.97.100 - 10.42.97.240";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
subnet = "10.42.97.0/24";
|
|
||||||
interface = "server";
|
|
||||||
option-data = [
|
|
||||||
{
|
|
||||||
name = "routers";
|
|
||||||
data = "10.42.97.1";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "domain-name";
|
|
||||||
data = "cloonar.com";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "domain-name-servers";
|
|
||||||
data = "10.42.97.1";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
reservations = [
|
|
||||||
{
|
|
||||||
hw-address = "1a:c4:04:6e:29:bd";
|
|
||||||
ip-address = "10.42.97.2";
|
|
||||||
server-hostname = "omada.cloonar.com";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "02:00:00:00:00:03";
|
|
||||||
ip-address = "10.42.97.5";
|
|
||||||
server-hostname = "web-02.cloonar.com";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "02:00:00:00:00:04";
|
|
||||||
ip-address = "10.42.97.6";
|
|
||||||
server-hostname = "matrix.cloonar.com";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "ea:db:d4:c1:18:ba";
|
|
||||||
ip-address = "10.42.97.50";
|
|
||||||
server-hostname = "git.cloonar.com";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "c2:4f:64:dd:13:0c";
|
|
||||||
ip-address = "10.42.97.20";
|
|
||||||
server-hostname = "home-assistant.cloonar.com";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "1a:c4:04:6e:29:02";
|
|
||||||
ip-address = "10.42.97.25";
|
|
||||||
server-hostname = "deconz.cloonar.com";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
pools = [
|
|
||||||
{
|
|
||||||
pool = "10.42.101.100 - 10.42.101.240";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
subnet = "10.42.101.0/24";
|
|
||||||
interface = "infrastructure";
|
|
||||||
option-data = [
|
|
||||||
{
|
|
||||||
name = "routers";
|
|
||||||
data = "10.42.101.1";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "domain-name";
|
|
||||||
data = "cloonar.com";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "domain-name-servers";
|
|
||||||
data = "10.42.101.1";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "capwap-ac-v4";
|
|
||||||
code = 138;
|
|
||||||
data = "10.42.97.2";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
reservations = [
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
pools = [
|
|
||||||
{
|
|
||||||
pool = "10.42.99.100 - 10.42.99.240";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
subnet = "10.42.99.0/24";
|
|
||||||
interface = "multimedia";
|
|
||||||
option-data = [
|
|
||||||
{
|
|
||||||
name = "routers";
|
|
||||||
data = "10.42.99.1";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "domain-name";
|
|
||||||
data = "cloonar.multimedia";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "domain-name-servers";
|
|
||||||
data = "10.42.99.1";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
reservations = [
|
|
||||||
{
|
|
||||||
hw-address = "c4:a7:2b:c7:ea:30";
|
|
||||||
ip-address = "10.42.99.10";
|
|
||||||
hostname = "metz.cloonar.multimedia";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "f0:2f:9e:d4:3b:21";
|
|
||||||
ip-address = "10.42.99.11";
|
|
||||||
hostname = "firetv-living";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "bc:33:29:ed:24:f0";
|
|
||||||
ip-address = "10.42.99.12";
|
|
||||||
hostname = "ps5";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "e4:2a:ac:32:3f:79";
|
|
||||||
ip-address = "10.42.99.13";
|
|
||||||
hostname = "xbox";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "98:b6:e9:b6:ef:f4";
|
|
||||||
ip-address = "10.42.99.14";
|
|
||||||
hostname = "switch";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "f0:2f:9e:c1:74:72";
|
|
||||||
ip-address = "10.42.99.21";
|
|
||||||
hostname = "firetv-bedroom";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "30:05:5c:56:62:37";
|
|
||||||
ip-address = "10.42.99.100";
|
|
||||||
server-hostname = "brn30055c566237";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
pools = [
|
|
||||||
{
|
|
||||||
pool = "10.42.254.10 - 10.42.254.254";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
subnet = "10.42.254.0/24";
|
|
||||||
interface = "guest";
|
|
||||||
option-data = [
|
|
||||||
{
|
|
||||||
name = "routers";
|
|
||||||
data = "10.42.254.1";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "domain-name-servers";
|
|
||||||
data = "9.9.9.9";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
pools = [
|
|
||||||
{
|
|
||||||
pool = "10.42.100.100 - 10.42.100.240";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
subnet = "10.42.100.0/24";
|
|
||||||
interface = "smart";
|
|
||||||
option-data = [
|
|
||||||
{
|
|
||||||
name = "routers";
|
|
||||||
data = "10.42.100.1";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "domain-name";
|
|
||||||
data = "cloonar.smart";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "domain-name-servers";
|
|
||||||
data = "10.42.100.1";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
reservations = [
|
|
||||||
# need fixed ips for all shelly devices
|
|
||||||
# living room 1 - 14
|
|
||||||
# 10.42.100.2 # bulb1
|
|
||||||
# 10.42.100.3 # bulb2
|
|
||||||
# 10.42.100.4 # bulb3
|
|
||||||
# 10.42.100.5 # bulb4
|
|
||||||
# 10.42.100.6 # bulb5
|
|
||||||
# 10.42.100.7 # bulb6
|
|
||||||
# 10.42.100.8 # piano
|
|
||||||
# 10.42.100.9 # switch
|
|
||||||
# 10.42.100.10 # steamdeck
|
|
||||||
# kitchen:
|
|
||||||
# 10.42.100.17 # coffee
|
|
||||||
# 10.42.100.18 # bar
|
|
||||||
# bedroom:
|
|
||||||
# 10.42.100.33 # switch
|
|
||||||
# 10.42.100.34 # button1
|
|
||||||
# 10.42.100.35 # button2
|
|
||||||
# 10.42.100.36 # readingled1
|
|
||||||
# 10.42.100.37 # readingled2
|
|
||||||
# 10.42.100.38 # bedled
|
|
||||||
# bath:
|
|
||||||
# 10.42.100.49 # switch
|
|
||||||
# 10.42.100.50 # bulb1
|
|
||||||
# 10.42.100.51 # bulb2
|
|
||||||
# 10.42.100.52 # smallswitch
|
|
||||||
# 10.42.100.53 # ht
|
|
||||||
# hallway:
|
|
||||||
# 10.42.100.65 # switch
|
|
||||||
# 10.42.100.66 # bulb1
|
|
||||||
# 10.42.100.67 # bulb2
|
|
||||||
# 10.42.100.68 # bulb3
|
|
||||||
# 10.42.100.69 # bulb4
|
|
||||||
# toilet:
|
|
||||||
# 10.42.100.81 # switch
|
|
||||||
# 10.42.100.82 # bulb
|
|
||||||
# storage:
|
|
||||||
# 10.42.100.97 # switch
|
|
||||||
|
|
||||||
{
|
|
||||||
hw-address = "60:a4:23:97:4a:ec";
|
|
||||||
ip-address = "10.42.100.21";
|
|
||||||
server-hostname = "shellymotionsensor-60A423974AEC";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "8c:aa:b5:61:6f:e2";
|
|
||||||
ip-address = "10.42.100.103";
|
|
||||||
server-hostname = "ShellyBulbDuo-8CAAB5616FE2";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "8c:aa:b5:61:6e:9e";
|
|
||||||
ip-address = "10.42.100.104";
|
|
||||||
server-hostname = "ShellyBulbDuo-8CAAB5616E9E";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "cc:50:e3:bc:27:64";
|
|
||||||
ip-address = "10.42.100.112";
|
|
||||||
server-hostname = "Nuki_Bridge_1A753F72";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "e8:db:84:a9:ea:be";
|
|
||||||
ip-address = "10.42.100.117";
|
|
||||||
server-hostname = "ShellyBulbDuo-E8DB84A9EABE";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "e8:db:84:a9:d1:8b";
|
|
||||||
ip-address = "10.42.100.119";
|
|
||||||
server-hostname = "shellycolorbulb-E8DB84A9D18B";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "3c:61:05:e5:96:e0";
|
|
||||||
ip-address = "10.42.100.120";
|
|
||||||
server-hostname = "shellycolorbulb-3C6105E596E0";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "e8:db:84:a9:d7:ef";
|
|
||||||
ip-address = "10.42.100.121";
|
|
||||||
server-hostname = "shellycolorbulb-E8DB84A9D7EF";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "e8:db:84:aa:51:aa";
|
|
||||||
ip-address = "10.42.100.122";
|
|
||||||
server-hostname = "shellycolorbulb-E8DB84AA51AA";
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
hw-address = "34:94:54:79:bc:57";
|
|
||||||
ip-address = "10.42.100.130";
|
|
||||||
server-hostname = "shellycolorbulb-34945479bc57";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "48:55:19:d9:a1:b2";
|
|
||||||
ip-address = "10.42.100.131";
|
|
||||||
server-hostname = "shellycolorbulb-485519d9a1b2";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "48:55:19:d9:ae:95";
|
|
||||||
ip-address = "10.42.100.132";
|
|
||||||
server-hostname = "shellycolorbulb-485519d9ae95";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "48:55:19:d9:4a:28";
|
|
||||||
ip-address = "10.42.100.133";
|
|
||||||
server-hostname = "shellycolorbulb-485519d94a28";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "48:55:19:da:6b:6a";
|
|
||||||
ip-address = "10.42.100.134";
|
|
||||||
server-hostname = "shellycolorbulb-485519da6b6a";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "48:55:19:d9:e0:18";
|
|
||||||
ip-address = "10.42.100.135";
|
|
||||||
server-hostname = "shellycolorbulb-485519d9e018";
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
hw-address = "34:6f:24:f3:af:ad";
|
|
||||||
ip-address = "10.42.100.137";
|
|
||||||
server-hostname = "daikin86604";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
hw-address = "34:6f:24:c1:f8:54";
|
|
||||||
ip-address = "10.42.100.139";
|
|
||||||
server-hostname = "daikin53800";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
valid-lifetime = 4000;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
{ config, pkgs, ... }:
|
|
||||||
let
|
|
||||||
domain = "sync.cloonar.com";
|
|
||||||
in {
|
|
||||||
sops.secrets.firefox-sync = { };
|
|
||||||
|
|
||||||
security.acme.certs."${domain}" = {
|
|
||||||
group = "nginx";
|
|
||||||
};
|
|
||||||
|
|
||||||
containers."firefox-sync" = {
|
|
||||||
autoStart = true;
|
|
||||||
ephemeral = false; # because of ssh key
|
|
||||||
privateNetwork = true;
|
|
||||||
hostBridge = "server";
|
|
||||||
hostAddress = "10.42.97.1";
|
|
||||||
localAddress = "10.42.97.51/24";
|
|
||||||
bindMounts = {
|
|
||||||
"/run/secrets/firefox-sync" = {
|
|
||||||
hostPath = "/run/secrets/firefox-sync";
|
|
||||||
isReadOnly = true;
|
|
||||||
};
|
|
||||||
"/var/lib/acme/${domain}/" = {
|
|
||||||
hostPath = "${config.security.acme.certs.${domain}.directory}";
|
|
||||||
isReadOnly = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
config = { lib, config, pkgs, ... }: {
|
|
||||||
networking = {
|
|
||||||
hostName = "firefox-sync";
|
|
||||||
useHostResolvConf = false;
|
|
||||||
defaultGateway = {
|
|
||||||
address = "10.42.97.1";
|
|
||||||
interface = "eth0";
|
|
||||||
};
|
|
||||||
firewall.enable = false;
|
|
||||||
nameservers = [ "10.42.97.1" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
services.nginx.enable = true;
|
|
||||||
services.nginx.virtualHosts."${domain}" = {
|
|
||||||
sslCertificate = "/var/lib/acme/${domain}/fullchain.pem";
|
|
||||||
sslCertificateKey = "/var/lib/acme/${domain}/key.pem";
|
|
||||||
sslTrustedCertificate = "/var/lib/acme/${domain}/chain.pem";
|
|
||||||
listen = [
|
|
||||||
{
|
|
||||||
addr = "0.0.0.0";
|
|
||||||
ssl = true;
|
|
||||||
port = 5000;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
locations."/" = {
|
|
||||||
proxyPass = "http://localhost:5001/";
|
|
||||||
recommendedProxySettings = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
services.mysql.package = pkgs.mariadb;
|
|
||||||
services.firefox-syncserver = {
|
|
||||||
enable = true;
|
|
||||||
singleNode = {
|
|
||||||
enable = true;
|
|
||||||
enableNginx = false;
|
|
||||||
hostname = domain;
|
|
||||||
};
|
|
||||||
settings = {
|
|
||||||
port = 5001;
|
|
||||||
tokenserver.enable = true;
|
|
||||||
};
|
|
||||||
secrets = "/run/secrets/firefox-sync";
|
|
||||||
logLevel = "trace";
|
|
||||||
};
|
|
||||||
|
|
||||||
services.openssh.enable = true;
|
|
||||||
users.users.root.openssh.authorizedKeys.keys = [
|
|
||||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7"
|
|
||||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIRQuPqH5fdX3KEw7DXzWEdO3AlUn1oSmtJtHB71ICoH Generated By Termius"
|
|
||||||
];
|
|
||||||
|
|
||||||
system.stateVersion = "23.05";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
{ config, pkgs, ... }:
|
|
||||||
let
|
|
||||||
configure_prom = builtins.toFile "prometheus.yml" ''
|
|
||||||
scrape_configs:
|
|
||||||
- job_name: 'server'
|
|
||||||
stream_parse: true
|
|
||||||
static_configs:
|
|
||||||
- targets:
|
|
||||||
- ${config.networking.hostName}:9100
|
|
||||||
'';
|
|
||||||
in {
|
|
||||||
sops.secrets.victoria-agent-env = {
|
|
||||||
sopsFile = ../utils/modules/victoriametrics/secrets.yaml;
|
|
||||||
};
|
|
||||||
|
|
||||||
services.prometheus.exporters.node.enable = true;
|
|
||||||
|
|
||||||
systemd.services.export-fw-to-prometheus = {
|
|
||||||
path = with pkgs; [victoriametrics];
|
|
||||||
enable = true;
|
|
||||||
after = ["network-online.target"];
|
|
||||||
wants = ["network-online.target"];
|
|
||||||
wantedBy = ["multi-user.target"];
|
|
||||||
script = "vmagent -promscrape.config=${configure_prom} -envflag.enable -remoteWrite.url=https://victoria-server.cloonar.com/api/v1/write";
|
|
||||||
|
|
||||||
serviceConfig = {
|
|
||||||
EnvironmentFile=config.sops.secrets.victoria-agent-env.path;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,169 +0,0 @@
|
|||||||
{ nixpkgs, pkgs, ... }: let
|
|
||||||
hostname = "git-02";
|
|
||||||
json = pkgs.formats.json { };
|
|
||||||
in {
|
|
||||||
microvm.vms = {
|
|
||||||
# gitea = {
|
|
||||||
# config = {
|
|
||||||
# microvm = {
|
|
||||||
# hypervisor = "cloud-hypervisor";
|
|
||||||
# shares = [
|
|
||||||
# {
|
|
||||||
# source = "/nix/store";
|
|
||||||
# mountPoint = "/nix/.ro-store";
|
|
||||||
# tag = "ro-store";
|
|
||||||
# proto = "virtiofs";
|
|
||||||
# }
|
|
||||||
# {
|
|
||||||
# source = "/var/lib/acme/git.cloonar.com";
|
|
||||||
# mountPoint = "/var/lib/acme/${hostname}.cloonar.com";
|
|
||||||
# tag = "ro-cert";
|
|
||||||
# proto = "virtiofs";
|
|
||||||
# }
|
|
||||||
# ];
|
|
||||||
# interfaces = [
|
|
||||||
# {
|
|
||||||
# type = "tap";
|
|
||||||
# id = "vm-${hostname}";
|
|
||||||
# mac = "02:00:00:00:00:01";
|
|
||||||
# }
|
|
||||||
# ];
|
|
||||||
# };
|
|
||||||
#
|
|
||||||
# imports = [
|
|
||||||
# ../fleet.nix
|
|
||||||
# ];
|
|
||||||
#
|
|
||||||
# environment.systemPackages = with pkgs; [
|
|
||||||
# vim # my preferred editor
|
|
||||||
# ];
|
|
||||||
#
|
|
||||||
# networking = {
|
|
||||||
# hostName = hostname;
|
|
||||||
# firewall = {
|
|
||||||
# enable = true;
|
|
||||||
# allowedTCPPorts = [ 22 80 443 ];
|
|
||||||
# };
|
|
||||||
# };
|
|
||||||
#
|
|
||||||
# services.nginx.enable = true;
|
|
||||||
# services.nginx.virtualHosts."${hostname}.cloonar.com" = {
|
|
||||||
# sslCertificate = "/var/lib/acme/${hostname}.cloonar.com/fullchain.pem";
|
|
||||||
# sslCertificateKey = "/var/lib/acme/${hostname}.cloonar.com/key.pem";
|
|
||||||
# sslTrustedCertificate = "/var/lib/acme/${hostname}.cloonar.com/chain.pem";
|
|
||||||
# forceSSL = true;
|
|
||||||
# locations."/" = {
|
|
||||||
# proxyPass = "http://localhost:3001/";
|
|
||||||
# };
|
|
||||||
# };
|
|
||||||
#
|
|
||||||
# services.gitea = {
|
|
||||||
# enable = true;
|
|
||||||
# appName = "Cloonar Gitea server"; # Give the site a name
|
|
||||||
# settings = {
|
|
||||||
# server = {
|
|
||||||
# ROOT_URL = "https://${hostname}.cloonar.com/";
|
|
||||||
# HTTP_PORT = 3001;
|
|
||||||
# DOMAIN = "${hostname}.cloonar.com";
|
|
||||||
# };
|
|
||||||
# openid = {
|
|
||||||
# ENABLE_OPENID_SIGNIN = true;
|
|
||||||
# ENABLE_OPENID_SIGNUP = true;
|
|
||||||
# WHITELISTED_URIS = "auth.cloonar.com";
|
|
||||||
# };
|
|
||||||
# service = {
|
|
||||||
# DISABLE_REGISTRATION = true;
|
|
||||||
# ALLOW_ONLY_EXTERNAL_REGISTRATION = true;
|
|
||||||
# SHOW_REGISTRATION_BUTTON = false;
|
|
||||||
# };
|
|
||||||
# actions.ENABLED=true;
|
|
||||||
# };
|
|
||||||
# };
|
|
||||||
#
|
|
||||||
# services.openssh.enable = true;
|
|
||||||
# users.users.root.openssh.authorizedKeys.keys = [
|
|
||||||
# "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7"
|
|
||||||
# "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIRQuPqH5fdX3KEw7DXzWEdO3AlUn1oSmtJtHB71ICoH Generated By Termius"
|
|
||||||
# ];
|
|
||||||
#
|
|
||||||
# system.stateVersion = "22.05";
|
|
||||||
# };
|
|
||||||
# };
|
|
||||||
|
|
||||||
gitea-runner = {
|
|
||||||
config = {
|
|
||||||
microvm = {
|
|
||||||
mem = 12288;
|
|
||||||
shares = [
|
|
||||||
{
|
|
||||||
source = "/nix/store";
|
|
||||||
mountPoint = "/nix/.ro-store";
|
|
||||||
tag = "ro-store";
|
|
||||||
proto = "virtiofs";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
source = "/run/secrets";
|
|
||||||
mountPoint = "/run/secrets";
|
|
||||||
tag = "ro-token";
|
|
||||||
proto = "virtiofs";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
volumes = [
|
|
||||||
{
|
|
||||||
image = "rootfs.img";
|
|
||||||
mountPoint = "/";
|
|
||||||
size = 102400;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
interfaces = [
|
|
||||||
{
|
|
||||||
type = "tap";
|
|
||||||
id = "vm-gitea-runner";
|
|
||||||
mac = "02:00:00:00:00:02";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; [
|
|
||||||
vim # my preferred editor
|
|
||||||
];
|
|
||||||
|
|
||||||
networking.hostName = "gitea-runner";
|
|
||||||
|
|
||||||
virtualisation.podman.enable = true;
|
|
||||||
|
|
||||||
services.gitea-actions-runner.instances.vm = {
|
|
||||||
enable = true;
|
|
||||||
url = "https://git.cloonar.com";
|
|
||||||
name = "vm";
|
|
||||||
tokenFile = "/run/secrets/gitea-runner-token";
|
|
||||||
labels = [
|
|
||||||
"ubuntu-latest:docker://shivammathur/node:latest"
|
|
||||||
];
|
|
||||||
settings = {
|
|
||||||
container = {
|
|
||||||
network = "podman";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
services.openssh.enable = true;
|
|
||||||
users.users.root.openssh.authorizedKeys.keys = [
|
|
||||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN/2SAFm50kraB1fepAizox/QRXxB7WbqVbH+5OPalDT47VIJGNKOKhixQoqhABHxEoLxdf/C83wxlCVlPV9poLfDgVkA3Lyt5r3tSFQ6QjjOJAgchWamMsxxyGBedhKvhiEzcr/Lxytnoz3kjDG8fqQJwEpdqMmJoMUfyL2Rqp16u+FQ7d5aJtwO8EUqovhMaNO7rggjPpV/uMOg+tBxxmscliN7DLuP4EMTA/FwXVzcFNbOx3K9BdpMRAaSJt4SWcJO2cS2KHA5n/H+PQI7nz5KN3Yr/upJN5fROhi/SHvK39QOx12Pv7FCuWlc+oR68vLaoCKYhnkl3DnCfc7A7"
|
|
||||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIRQuPqH5fdX3KEw7DXzWEdO3AlUn1oSmtJtHB71ICoH Generated By Termius"
|
|
||||||
];
|
|
||||||
|
|
||||||
system.stateVersion = "22.05";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
sops.secrets.gitea-runner-token = {};
|
|
||||||
|
|
||||||
environment = {
|
|
||||||
systemPackages = [
|
|
||||||
pkgs.qemu
|
|
||||||
pkgs.quickemu
|
|
||||||
];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
{ config, ... }: {
|
|
||||||
services.home-assistant.config = {
|
|
||||||
sensor = [
|
|
||||||
{
|
|
||||||
platform = "rest";
|
|
||||||
name = "creality extruder";
|
|
||||||
resource = "http://k1c-63e9.cloonar.smart:7125/printer/objects/query?extruder";
|
|
||||||
value_template = "OK";
|
|
||||||
json_attributes_path = "$.result.status.extruder";
|
|
||||||
json_attributes = [
|
|
||||||
"pressure_advance"
|
|
||||||
"power"
|
|
||||||
"target"
|
|
||||||
"temperature"
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
platform = "rest";
|
|
||||||
name = "creality print stats";
|
|
||||||
resource = "http://k1c-63e9.cloonar.smart:7125/printer/objects/query?print_stats";
|
|
||||||
value_template = "OK";
|
|
||||||
json_attributes_path = "$.result.status.print_stats";
|
|
||||||
json_attributes = [
|
|
||||||
"filename"
|
|
||||||
"total_duration"
|
|
||||||
"print_duration"
|
|
||||||
"filament_used"
|
|
||||||
"state"
|
|
||||||
"message"
|
|
||||||
];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
platform = "template";
|
|
||||||
sensors = {
|
|
||||||
crality_hotend_actual = {
|
|
||||||
friendly_name = "Hot End Actual";
|
|
||||||
value_template = "{{ state_attr('sensor.creality_extruder', 'temperature') | float | round(1) }}";
|
|
||||||
device_class = "temperature";
|
|
||||||
unit_of_measurement = "°C";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
"automation 3d printer state" = {
|
|
||||||
alias = "3d printer state change";
|
|
||||||
trigger = [
|
|
||||||
{
|
|
||||||
platform = "template";
|
|
||||||
value_template = "{{ state_attr('sensor.creality_print_stats','state') == 'standby' }}";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
action = {
|
|
||||||
service = "notify.mobile_app_dominiks_iphone";
|
|
||||||
data = {
|
|
||||||
message = "Printer status changed to {{ state_attr('sensor.creality_print_stats','state') }}";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
{
|
|
||||||
services.home-assistant.extraComponents = [
|
|
||||||
"daikin"
|
|
||||||
"enocean"
|
|
||||||
];
|
|
||||||
|
|
||||||
services.home-assistant.config = {
|
|
||||||
sensor = [
|
|
||||||
{
|
|
||||||
name = "Living Room Window Handle 2";
|
|
||||||
platform = "enocean";
|
|
||||||
id = [ 129 0 227 53 ];
|
|
||||||
device_class = "windowhandle";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "Living Room Window Handle 1";
|
|
||||||
platform = "enocean";
|
|
||||||
id = [ 129 0 229 8 ];
|
|
||||||
device_class = "windowhandle";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
"automation ac_livingroom" = {
|
|
||||||
alias = "ac_livingroom";
|
|
||||||
trigger = [
|
|
||||||
{
|
|
||||||
platform = "state";
|
|
||||||
entity_id = "sensor.windowhandle_living_room_window_handle_1";
|
|
||||||
to = [ "open" "tilt" ];
|
|
||||||
}
|
|
||||||
{
|
|
||||||
platform = "state";
|
|
||||||
entity_id = "sensor.windowhandle_living_room_window_handle_2";
|
|
||||||
to = [ "open" "tilt" ];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
action = {
|
|
||||||
service = "climate.set_hvac_mode";
|
|
||||||
target = {
|
|
||||||
entity_id = "climate.living_room";
|
|
||||||
};
|
|
||||||
data = {
|
|
||||||
hvac_mode = "off";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
"automation ac_eco" = {
|
|
||||||
alias = "ac_eco";
|
|
||||||
trigger = {
|
|
||||||
platform = "state";
|
|
||||||
entity_id = [
|
|
||||||
"climate.living_room"
|
|
||||||
"climate.bedroom"
|
|
||||||
];
|
|
||||||
to = [
|
|
||||||
"heat"
|
|
||||||
"cold"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
action = {
|
|
||||||
service = "climate.set_preset_mode";
|
|
||||||
target = {
|
|
||||||
entity_id = "{{ trigger.entity_id }}";
|
|
||||||
};
|
|
||||||
data = {
|
|
||||||
preset_mode = "eco";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
"automation bedroom_ac_on" = {
|
|
||||||
alias = "bedroom ac on";
|
|
||||||
trigger = {
|
|
||||||
platform = "time";
|
|
||||||
at = "00:30:00";
|
|
||||||
};
|
|
||||||
action = {
|
|
||||||
choose = [
|
|
||||||
{
|
|
||||||
conditions = [ "{{ states('sensor.bedroom_ac_inside_temperature') > 25 and states('sensor.bedroom_ac_outside_temperature') > 22 }}" ];
|
|
||||||
sequence = [
|
|
||||||
{
|
|
||||||
service = "climate.set_hvac_mode";
|
|
||||||
target = {
|
|
||||||
entity_id = "climate.bedroom";
|
|
||||||
};
|
|
||||||
data = {
|
|
||||||
hvac_mode = "cold";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
"automation bedroom_ac_off" = {
|
|
||||||
alias = "bedroom ac on";
|
|
||||||
trigger = {
|
|
||||||
platform = "template";
|
|
||||||
value_template = ''
|
|
||||||
{{ now().timestamp() | timestamp_custom('%H:%M') == (as_timestamp(strptime(states('sensor.bedtime_alarm'), "%H:%M")) - 1800) | timestamp_custom('%H:%M', false) }}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
action = {
|
|
||||||
service = "climate.set_hvac_mode";
|
|
||||||
target = {
|
|
||||||
entity_id = "climate.bedroom";
|
|
||||||
};
|
|
||||||
data = {
|
|
||||||
hvac_mode = "off";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user