# Auto-generated by compose2nix. { pkgs, lib, config, ... }: { # Runtime virtualisation.podman = { enable = true; autoPrune.enable = true; dockerCompat = true; }; # Enable container name DNS for all Podman networks. networking.firewall.interfaces = let matchAll = if !config.networking.nftables.enable then "podman+" else "podman*"; in { "${matchAll}".allowedUDPPorts = [ 53 ]; }; virtualisation.oci-containers.backend = "podman"; # Containers virtualisation.oci-containers.containers."remnawave" = { image = "remnawave/backend:2"; environment = { "API_INSTANCES" = "1"; "APP_PORT" = "3000"; "BANDWIDTH_USAGE_NOTIFICATIONS_ENABLED" = "false"; "BANDWIDTH_USAGE_NOTIFICATIONS_THRESHOLD" = "[60, 80]"; "CLOUDFLARE_TOKEN" = "ey..."; "DATABASE_URL" = "postgresql://remnawave:remnawave@remnawave-db:5432/postgres"; "FRONT_END_DOMAIN" = "*"; "IS_DOCS_ENABLED" = "false"; "IS_TELEGRAM_NOTIFICATIONS_ENABLED" = "false"; "JWT_API_TOKENS_SECRET" = "787aa44c10130a9fa17ea3ea50c1248dd3e868f74941b96c09d608051399f88b95b67cd68d045aa39658b4b3fe933bf2b2c1437522498976f39f85ae1eab40da"; "JWT_AUTH_SECRET" = "2bc14bacb6b82ce9e3ef69f8dd7bfb6b8a531f4f516902735d1d8f1bac8ff9b5077398f95b942b1adafc0ca1da4cdfd24a18539fa6eb26bee3f597a45deac94a"; "METRICS_PASS" = "admin"; "METRICS_PORT" = "3001"; "METRICS_USER" = "admin"; "NOT_CONNECTED_USERS_NOTIFICATIONS_AFTER_HOURS" = "[6, 24, 48]"; "NOT_CONNECTED_USERS_NOTIFICATIONS_ENABLED" = "false"; "PANEL_DOMAIN" = "rw.zeroq.ru"; "POSTGRES_DB" = "remnawave"; "POSTGRES_PASSWORD" = "gQLqOm2jK/Z1oBXCD18XSgr76M8ZqkVhHZbNKvZQXnY="; "POSTGRES_USER" = "remnawave"; "REDIS_SOCKET" = "/var/run/valkey/valkey.sock"; "SCALAR_PATH" = "/scalar"; "SUB_PUBLIC_DOMAIN" = "rw.zeroq.ru/api/sub"; "SWAGGER_PATH" = "/docs"; "TELEGRAM_BOT_TOKEN" = "change_me"; "TELEGRAM_NOTIFY_CRM" = "change_me"; "TELEGRAM_NOTIFY_NODES" = "change_me"; "TELEGRAM_NOTIFY_SERVICE" = "change_me"; "TELEGRAM_NOTIFY_TBLOCKER" = "change_me"; "TELEGRAM_NOTIFY_USERS" = "change_me"; "WEBHOOK_ENABLED" = "false"; "WEBHOOK_SECRET_HEADER" = "vsmu67Kmg6R8FjIOF1WUY8LWBHie4scdEqrfsKmyf4IAf8dY3nFS0wwYHkhh6ZvQ"; "WEBHOOK_URL" = "https://your-webhook-url.com/endpoint"; }; volumes = [ "valkey-socket:/var/run/valkey:rw" ]; ports = [ "127.0.0.1:3000:3000/tcp" "127.0.0.1:3001:3001/tcp" ]; dependsOn = [ "remnawave-db" "remnawave-redis" ]; log-driver = "journald"; extraOptions = [ "--health-cmd=curl -f http://localhost:3001/health" "--health-interval=30s" "--health-retries=3" "--health-start-period=30s" "--health-timeout=5s" "--hostname=remnawave" "--network-alias=remnawave" "--network=remnawave-network" ]; }; systemd.services."podman-remnawave" = { serviceConfig = { Restart = lib.mkOverride 90 "always"; }; after = [ "podman-network-remnawave-network.service" "podman-volume-valkey-socket.service" ]; requires = [ "podman-network-remnawave-network.service" "podman-volume-valkey-socket.service" ]; partOf = [ "podman-compose-remnawave-root.target" ]; wantedBy = [ "podman-compose-remnawave-root.target" ]; }; virtualisation.oci-containers.containers."remnawave-db" = { image = "postgres:17.6"; environment = { "API_INSTANCES" = "1"; "APP_PORT" = "3000"; "BANDWIDTH_USAGE_NOTIFICATIONS_ENABLED" = "false"; "BANDWIDTH_USAGE_NOTIFICATIONS_THRESHOLD" = "[60, 80]"; "CLOUDFLARE_TOKEN" = "ey..."; "DATABASE_URL" = "postgresql://remnawave:remnawave@remnawave-db:5432/postgres"; "FRONT_END_DOMAIN" = "*"; "IS_DOCS_ENABLED" = "false"; "IS_TELEGRAM_NOTIFICATIONS_ENABLED" = "false"; "JWT_API_TOKENS_SECRET" = "787aa44c10130a9fa17ea3ea50c1248dd3e868f74941b96c09d608051399f88b95b67cd68d045aa39658b4b3fe933bf2b2c1437522498976f39f85ae1eab40da"; "JWT_AUTH_SECRET" = "2bc14bacb6b82ce9e3ef69f8dd7bfb6b8a531f4f516902735d1d8f1bac8ff9b5077398f95b942b1adafc0ca1da4cdfd24a18539fa6eb26bee3f597a45deac94a"; "METRICS_PASS" = "admin"; "METRICS_PORT" = "3001"; "METRICS_USER" = "admin"; "NOT_CONNECTED_USERS_NOTIFICATIONS_AFTER_HOURS" = "[6, 24, 48]"; "NOT_CONNECTED_USERS_NOTIFICATIONS_ENABLED" = "false"; "PANEL_DOMAIN" = "rw.zeroq.ru"; "POSTGRES_DB" = ""; "POSTGRES_PASSWORD" = ""; "POSTGRES_USER" = ""; "REDIS_SOCKET" = "/var/run/valkey/valkey.sock"; "SCALAR_PATH" = "/scalar"; "SUB_PUBLIC_DOMAIN" = "rw.zeroq.ru/api/sub"; "SWAGGER_PATH" = "/docs"; "TELEGRAM_BOT_TOKEN" = "change_me"; "TELEGRAM_NOTIFY_CRM" = "change_me"; "TELEGRAM_NOTIFY_NODES" = "change_me"; "TELEGRAM_NOTIFY_SERVICE" = "change_me"; "TELEGRAM_NOTIFY_TBLOCKER" = "change_me"; "TELEGRAM_NOTIFY_USERS" = "change_me"; "TZ" = "UTC"; "WEBHOOK_ENABLED" = "false"; "WEBHOOK_SECRET_HEADER" = "vsmu67Kmg6R8FjIOF1WUY8LWBHie4scdEqrfsKmyf4IAf8dY3nFS0wwYHkhh6ZvQ"; "WEBHOOK_URL" = "https://your-webhook-url.com/endpoint"; }; volumes = [ "remnawave-db-data:/var/lib/postgresql/data:rw" ]; ports = [ "127.0.0.1:6767:5432/tcp" ]; log-driver = "journald"; extraOptions = [ "--health-cmd=pg_isready -U \${POSTGRES_USER} -d \${POSTGRES_DB}" "--health-interval=3s" "--health-retries=3" "--health-timeout=10s" "--hostname=remnawave-db" "--network-alias=remnawave-db" "--network=remnawave-network" ]; }; systemd.services."podman-remnawave-db" = { serviceConfig = { Restart = lib.mkOverride 90 "always"; }; after = [ "podman-network-remnawave-network.service" "podman-volume-remnawave-db-data.service" ]; requires = [ "podman-network-remnawave-network.service" "podman-volume-remnawave-db-data.service" ]; partOf = [ "podman-compose-remnawave-root.target" ]; wantedBy = [ "podman-compose-remnawave-root.target" ]; }; virtualisation.oci-containers.containers."remnawave-redis" = { image = "valkey/valkey:9-alpine"; volumes = [ "valkey-socket:/var/run/valkey:rw" ]; cmd = [ "valkey-server" "--save" "" "--appendonly" "no" "--maxmemory-policy" "noeviction" "--loglevel" "warning" "--unixsocket" "/var/run/valkey/valkey.sock" "--unixsocketperm" "777" "--port" "0" ]; log-driver = "journald"; extraOptions = [ "--health-cmd=[\"valkey-cli\", \"-s\", \"/var/run/valkey/valkey.sock\", \"ping\"]" "--health-interval=3s" "--health-retries=3" "--health-timeout=3s" "--hostname=remnawave-redis" "--network-alias=remnawave-redis" "--network=remnawave-network" ]; }; systemd.services."podman-remnawave-redis" = { serviceConfig = { Restart = lib.mkOverride 90 "always"; }; after = [ "podman-network-remnawave-network.service" "podman-volume-valkey-socket.service" ]; requires = [ "podman-network-remnawave-network.service" "podman-volume-valkey-socket.service" ]; partOf = [ "podman-compose-remnawave-root.target" ]; wantedBy = [ "podman-compose-remnawave-root.target" ]; }; # Networks systemd.services."podman-network-remnawave-network" = { path = [ pkgs.podman ]; serviceConfig = { Type = "oneshot"; RemainAfterExit = true; ExecStop = "podman network rm -f remnawave-network"; }; script = '' podman network inspect remnawave-network || podman network create remnawave-network --driver=bridge ''; partOf = [ "podman-compose-remnawave-root.target" ]; wantedBy = [ "podman-compose-remnawave-root.target" ]; }; # Volumes systemd.services."podman-volume-remnawave-db-data" = { path = [ pkgs.podman ]; serviceConfig = { Type = "oneshot"; RemainAfterExit = true; }; script = '' podman volume inspect remnawave-db-data || podman volume create remnawave-db-data --driver=local ''; partOf = [ "podman-compose-remnawave-root.target" ]; wantedBy = [ "podman-compose-remnawave-root.target" ]; }; systemd.services."podman-volume-valkey-socket" = { path = [ pkgs.podman ]; serviceConfig = { Type = "oneshot"; RemainAfterExit = true; }; script = '' podman volume inspect valkey-socket || podman volume create valkey-socket --driver=local ''; partOf = [ "podman-compose-remnawave-root.target" ]; wantedBy = [ "podman-compose-remnawave-root.target" ]; }; # Root service # When started, this will automatically create all resources and start # the containers. When stopped, this will teardown all resources. systemd.targets."podman-compose-remnawave-root" = { unitConfig = { Description = "Root target generated by compose2nix."; }; wantedBy = [ "multi-user.target" ]; }; }