# NixOS Deployment ## Flake outputs | Output | Description | |---|---| | `packages.default` | The `crypto-alert-bot` binary | | `devShells.default` | Dev shell with Go toolchain, gopls, golangci-lint, go-migrate | | `nixosModules.default` | NixOS module that runs the bot as a systemd service | --- ## NixOS module The module handles all infrastructure automatically: - Enables and configures `services.postgresql` - Creates the `crypto-alert-bot` database and PostgreSQL role - Connects via Unix socket using peer authentication (no password) - Creates a dedicated system user `crypto-alert-bot` - Runs the bot as a hardened systemd service The only secret you need to supply is the Telegram bot token, via a file path. ### Options | Option | Type | Default | Description | |---|---|---|---| | `enable` | bool | `false` | Enable the service | | `package` | package | flake default | Override the binary package | | `telegramTokenFile` | path | — | **Required.** Path to a file containing the bot token | | `dbName` | string | `"crypto-alert-bot"` | PostgreSQL database name | | `logLevel` | `debug\|info\|warn\|error` | `"info"` | Log verbosity | | `logEncoding` | `console\|json` | `"json"` | Log format | | `logServiceName` | string | `"alert-bot"` | Service name field in log output | | `bybitBaseUrl` | string | `"https://api.bybit.com"` | Bybit REST API base URL | ### Minimal configuration ```nix # flake.nix of your NixOS config { inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; crypto-alert-bot.url = "github:youruser/crypto_alert_bot"; agenix.url = "github:ryantm/agenix"; }; outputs = { nixpkgs, crypto-alert-bot, agenix, ... }: { nixosConfigurations.myhost = nixpkgs.lib.nixosSystem { modules = [ crypto-alert-bot.nixosModules.default agenix.nixosModules.default ./configuration.nix ]; }; }; } ``` ```nix # configuration.nix services.crypto-alert-bot = { enable = true; telegramTokenFile = config.age.secrets.telegram-token.path; }; ``` --- ## Encrypting the Telegram token with agenix [agenix](https://github.com/ryantm/agenix) encrypts secrets with [age](https://github.com/FiloSottile/age) and decrypts them at boot using SSH host keys already present on the machine. Encrypted secret files are safe to commit to your NixOS config repository. ### 1. Install age and agenix ```bash # age — encryption tool nix shell nixpkgs#age # agenix CLI — manages encrypted secret files nix shell github:ryantm/agenix ``` ### 2. Collect recipient public keys agenix encrypts each secret for one or more recipients. Typical recipients: - **SSH host key** of the target machine (used for decryption at boot) - **Your personal SSH key** (used so you can re-encrypt or rotate secrets from your workstation) ```bash # Get the host's SSH public key (run on the target machine or from your config) cat /etc/ssh/ssh_host_ed25519_key.pub # Get your personal SSH public key cat ~/.ssh/id_ed25519.pub ``` ### 3. Create secrets.nix In the root of your NixOS config repository, create `secrets/secrets.nix`. This file declares which keys can decrypt each secret — it is **not** sensitive and should be committed. ```nix # secrets/secrets.nix let # SSH public key of the target host host = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... root@myhost"; # Your personal SSH public key (for re-encryption from your workstation) me = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... user@workstation"; in { "telegram-token.age".publicKeys = [ host me ]; } ``` ### 4. Encrypt the token ```bash cd secrets/ # agenix will open $EDITOR so you can type the token, then encrypt on save agenix -e telegram-token.age ``` Type (or paste) the raw token value — just the token string, no quotes, no newline: ``` 1234567890:ABCdefGHIjklMNOpqrSTUvwxYZ ``` Save and close the editor. agenix writes `telegram-token.age` — this encrypted file is safe to commit. ### 5. Wire the secret into your NixOS config ```nix # configuration.nix { config, ... }: { # Declare the secret; agenix decrypts it at boot to /run/agenix/telegram-token age.secrets.telegram-token = { file = ./secrets/telegram-token.age; # The service user must be able to read the decrypted file owner = "crypto-alert-bot"; mode = "0400"; }; services.crypto-alert-bot = { enable = true; telegramTokenFile = config.age.secrets.telegram-token.path; # Optionally tune logging: # logLevel = "debug"; # logEncoding = "console"; }; } ``` ### 6. Deploy ```bash nixos-rebuild switch --flake .#myhost ``` At boot, agenix decrypts `telegram-token.age` using the host's SSH private key and places the plaintext at `/run/agenix/telegram-token` (mode 0400, owned by `crypto-alert-bot`). The bot service reads the token from that path at start time. ### Rotating the token Edit the encrypted file from your workstation with your personal SSH key: ```bash cd secrets/ agenix -e telegram-token.age # opens $EDITOR with decrypted content # change the value, save, close git add telegram-token.age && git commit -m "rotate telegram token" ``` Then redeploy: ```bash nixos-rebuild switch --flake .#myhost systemctl restart crypto-alert-bot ``` --- ## Development shell ```bash nix develop # Start the database locally (Docker or Podman) docker compose up -d # Run the bot CONFIG_PATH=./internal/config/local.yml go run ./cmd/app/main.go ```