diff --git a/configuration/default.nix b/configuration/default.nix index d84302a..52be9a1 100644 --- a/configuration/default.nix +++ b/configuration/default.nix @@ -1,18 +1,29 @@ { - config, pkgs, lib, + modulesPath, ... }: { imports = [ + "${modulesPath}/profiles/headless.nix" + (import ../modules) + ./services/gitea.nix ./services/nextcloud.nix ./services/webserver.nix ./services/starbound.nix - ./ids.nix + ./services/postgres.nix ./sops.nix ]; + nixpkgs.overlays = [ + (final: prev: { + local = import ../pkgs { + pkgs = prev; + }; + }) + ]; + nix = { package = pkgs.nixFlakes; extraOptions = '' @@ -24,7 +35,7 @@ }; nixpkgs.config.allowUnfreePredicate = pkg: - builtins.elem (lib.getName pkg) ["steam-runtime" "steamcmd"]; + builtins.elem (lib.getName pkg) ["steam-original" "steam-runtime" "steamcmd"]; # Optimization for minecraft servers, see: # https://bugs.mojang.com/browse/MC-183518 @@ -37,7 +48,7 @@ useDHCP = false; interfaces.eth0.useDHCP = true; - firewall.allowedTCPPorts = [80 443 2222 2221 21025]; + firewall.allowedTCPPorts = [80 443 2222 21025]; }; time.timeZone = "Europe/London"; @@ -66,32 +77,12 @@ recommendedProxySettings = true; clientMaxBodySize = "10G"; domain = "tlater.net"; - - virtualHosts = let - proxyPassToPort = port: extra: - lib.recursiveUpdate { - forceSSL = true; - enableACME = true; - locations."/".proxyPass = "http://127.0.0.1:${toString port}"; - extraConfig = '' - add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; - ''; - } - extra; - domain = config.services.nginx.domain; - in { - "${domain}" = proxyPassToPort 3002 {serverAliases = ["www.${domain}"];}; - "gitea.${domain}" = proxyPassToPort 3000 {}; - "nextcloud.${domain}" = proxyPassToPort 3001 {}; - }; }; security.acme = { - email = "tm@tlater.net"; + defaults.email = "tm@tlater.net"; acceptTerms = true; }; - virtualisation.oci-containers.backend = "podman"; - system.stateVersion = "20.09"; } diff --git a/configuration/linode.nix b/configuration/hardware-specific/linode/default.nix similarity index 87% rename from configuration/linode.nix rename to configuration/hardware-specific/linode/default.nix index 7d6a780..3cd3570 100644 --- a/configuration/linode.nix +++ b/configuration/hardware-specific/linode/default.nix @@ -1,4 +1,8 @@ { + imports = [ + ./hardware-configuration.nix + ]; + # Required for the lish console boot.kernelParams = ["console=ttyS0,19200n8"]; diff --git a/configuration/hardware-configuration.nix b/configuration/hardware-specific/linode/hardware-configuration.nix similarity index 100% rename from configuration/hardware-configuration.nix rename to configuration/hardware-specific/linode/hardware-configuration.nix diff --git a/configuration/hardware-specific/vm.nix b/configuration/hardware-specific/vm.nix new file mode 100644 index 0000000..aed39e4 --- /dev/null +++ b/configuration/hardware-specific/vm.nix @@ -0,0 +1,17 @@ +{lib, ...}: { + users.users.tlater.password = "insecure"; + + # Disable graphical tty so -curses works + boot.kernelParams = ["nomodeset"]; + + # Sets the base domain for nginx to localhost so that we + # can easily test locally with the VM. + services.nginx.domain = lib.mkOverride 99 "localhost"; + + # Use the staging secrets + sops.defaultSopsFile = lib.mkOverride 99 ../../keys/staging.yaml; + + # # Set up VM settings to match real VPS + # virtualisation.memorySize = 3941; + # virtualisation.cores = 2; +} diff --git a/configuration/ids.nix b/configuration/ids.nix deleted file mode 100644 index 352b4d3..0000000 --- a/configuration/ids.nix +++ /dev/null @@ -1,11 +0,0 @@ -{...}: { - ids.uids = { - # System user ids start at 400 (see nixos/modules/programs/shadow.nix) - webserver = 400; - # The limit is 999 - }; - - ids.gids = { - webserver = 400; - }; -} diff --git a/configuration/services/configs/nginx-nextcloud.conf b/configuration/services/configs/nginx-nextcloud.conf deleted file mode 100644 index 7c6ad78..0000000 --- a/configuration/services/configs/nginx-nextcloud.conf +++ /dev/null @@ -1,167 +0,0 @@ -worker_processes auto; - -error_log /var/log/nginx/error.log warn; -pid /var/run/nginx.pid; - - -events { - worker_connections 1024; -} - - -http { - include /etc/nginx/mime.types; - default_type application/octet-stream; - - log_format main '$remote_addr - $remote_user [$time_local] "$request" ' - '$status $body_bytes_sent "$http_referer" ' - '"$http_user_agent" "$http_x_forwarded_for"'; - - access_log /var/log/nginx/access.log main; - - sendfile on; - #tcp_nopush on; - - keepalive_timeout 65; - - #gzip on; - - upstream php-handler { - server localhost:9000; - } - - server { - listen 80; - - # HSTS settings - # WARNING: Only add the preload option once you read about - # the consequences in https://hstspreload.org/. This option - # will add the domain to a hardcoded list that is shipped - # in all major browsers and getting removed from this list - # could take several months. - #add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always; - - # HTTP response headers borrowed from Nextcloud `.htaccess` - add_header Referrer-Policy "no-referrer" always; - add_header X-Content-Type-Options "nosniff" always; - add_header X-Download-Options "noopen" always; - add_header X-Frame-Options "SAMEORIGIN" always; - add_header X-Permitted-Cross-Domain-Policies "none" always; - add_header X-Robots-Tag "none" always; - add_header X-XSS-Protection "1; mode=block" always; - - # Remove X-Powered-By, which is an information leak - fastcgi_hide_header X-Powered-By; - - # Path to the root of your installation - root /var/www/html; - - # Specify how to handle directories -- specifying `/index.php$request_uri` - # here as the fallback means that Nginx always exhibits the desired behaviour - # when a client requests a path that corresponds to a directory that exists - # on the server. In particular, if that directory contains an index.php file, - # that file is correctly served; if it doesn't, then the request is passed to - # the front-end controller. This consistent behaviour means that we don't need - # to specify custom rules for certain paths (e.g. images and other assets, - # `/updater`, `/ocm-provider`, `/ocs-provider`), and thus - # `try_files $uri $uri/ /index.php$request_uri` - # always provides the desired behaviour. - index index.php index.html /index.php$request_uri; - - # Rule borrowed from `.htaccess` to handle Microsoft DAV clients - location = / { - if ( $http_user_agent ~ ^DavClnt ) { - return 302 /remote.php/webdav/$is_args$args; - } - } - - location = /robots.txt { - allow all; - log_not_found off; - access_log off; - } - - # Make a regex exception for `/.well-known` so that clients can still - # access it despite the existence of the regex rule - # `location ~ /(\.|autotest|...)` which would otherwise handle requests - # for `/.well-known`. - location ^~ /.well-known { - # The rules in this block are an adaptation of the rules - # in `.htaccess` that concern `/.well-known`. - - location = /.well-known/carddav { return 301 /remote.php/dav/; } - location = /.well-known/caldav { return 301 /remote.php/dav/; } - - location /.well-known/acme-challenge { try_files $uri $uri/ =404; } - location /.well-known/pki-validation { try_files $uri $uri/ =404; } - - # Let Nextcloud's API for `/.well-known` URIs handle all other - # requests by passing them to the front-end controller. - return 301 /index.php$request_uri; - } - - # set max upload size - client_max_body_size 10G; - fastcgi_buffers 64 4K; - - # Enable gzip but do not remove ETag headers - gzip on; - gzip_vary on; - gzip_comp_level 4; - gzip_min_length 256; - gzip_proxied expired no-cache no-store private no_last_modified no_etag auth; - gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy; - - # Pagespeed is not supported by Nextcloud, so if your server is built - # with the `ngx_pagespeed` module, uncomment this line to disable it. - #pagespeed off; - - # Rules borrowed from `.htaccess` to hide certain paths from clients - location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/) { return 404; } - location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) { return 404; } - - # Ensure this block, which passes PHP files to the PHP process, is above the blocks - # which handle static assets (as seen below). If this block is not declared first, - # then Nginx will encounter an infinite rewriting loop when it prepends `/index.php` - # to the URI, resulting in a HTTP 500 error response. - location ~ \.php(?:$|/) { - fastcgi_split_path_info ^(.+?\.php)(/.*)$; - set $path_info $fastcgi_path_info; - - try_files $fastcgi_script_name =404; - - include fastcgi_params; - fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; - fastcgi_param PATH_INFO $path_info; - #fastcgi_param HTTPS on; - - fastcgi_param modHeadersAvailable true; # Avoid sending the security headers twice - fastcgi_param front_controller_active true; # Enable pretty urls - fastcgi_pass php-handler; - - fastcgi_intercept_errors on; - fastcgi_request_buffering off; - } - - location ~ \.(?:css|js|svg|gif)$ { - try_files $uri /index.php$request_uri; - expires 6M; # Cache-Control policy borrowed from `.htaccess` - access_log off; # Optional: Don't log access to assets - } - - location ~ \.woff2?$ { - try_files $uri /index.php$request_uri; - expires 7d; # Cache-Control policy borrowed from `.htaccess` - access_log off; # Optional: Don't log access to assets - } - - # Rule borrowed from `.htaccess` - location /remote { - return 301 /remote.php$request_uri; - } - - location / { - try_files $uri $uri/ /index.php$request_uri; - } - } -} diff --git a/configuration/services/gitea.nix b/configuration/services/gitea.nix index 5f9ebd0..cd99951 100644 --- a/configuration/services/gitea.nix +++ b/configuration/services/gitea.nix @@ -1,48 +1,31 @@ -{config, ...}: { - users = { - extraUsers.gitea = { - uid = config.ids.uids.git; - isSystemUser = true; - description = "Gitea Service"; - group = config.users.extraGroups.gitea.name; - }; - extraGroups.gitea = {gid = config.ids.gids.git;}; +{config, ...}: let + domain = "gitea.${config.services.nginx.domain}"; +in { + services.gitea = { + inherit domain; + enable = true; + + httpAddress = "127.0.0.1"; + database.type = "postgres"; + + ssh.clonePort = 2222; + rootUrl = "https://${domain}/"; + cookieSecure = true; + + appName = "Gitea: Git with a cup of tea"; + disableRegistration = true; }; - virtualisation.pods.gitea = { - hostname = "gitea.tlater.net"; - publish = ["3000:3000" "2221:2221"]; - network = "slirp4netns"; + # Set up SSL + services.nginx.virtualHosts."${domain}" = let + inherit (config.services.gitea) httpAddress httpPort; + in { + forceSSL = true; + enableACME = true; + extraConfig = '' + add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always; + ''; - containers = { - gitea = { - image = "gitea/gitea:latest"; - volumes = ["gitea:/data:Z" "/etc/localtime:/etc/localtime:ro"]; - dependsOn = ["postgres"]; - - environment = { - DB_TYPE = "postgres"; - DB_HOST = "localhost:5432"; - DB_NAME = "gitea"; - DB_USER = "gitea"; - - USER_UID = toString config.users.extraUsers.gitea.uid; - USER_GID = toString config.users.extraGroups.gitea.gid; - - RUN_MODE = "prod"; - DOMAIN = "gitea.tlater.net"; - SSH_PORT = "2221"; - }; - }; - - postgres = { - image = "postgres:alpine"; - environment = { - POSTGRES_DB = "gitea"; - POSTGRES_USER = "gitea"; - }; - volumes = ["gitea-postgres-14:/var/lib/postgresql/data"]; - }; - }; + locations."/".proxyPass = "http://${httpAddress}:${toString httpPort}"; }; } diff --git a/configuration/services/nextcloud.nix b/configuration/services/nextcloud.nix index 5b32cf2..ce43280 100644 --- a/configuration/services/nextcloud.nix +++ b/configuration/services/nextcloud.nix @@ -1,53 +1,99 @@ -{config, ...}: { - virtualisation.pods.nextcloud = { - hostname = "nextcloud.tlater.net"; - publish = ["3001:80"]; - network = "slirp4netns"; +{ + pkgs, + config, + ... +}: let + inherit (pkgs) fetchNextcloudApp; + nextcloud = pkgs.nextcloud24; + hostName = "nextcloud.${config.services.nginx.domain}"; +in { + services.nextcloud = { + inherit hostName; - containers = { - nextcloud = { - image = "nextcloud:fpm-alpine"; - dependsOn = ["postgres"]; - volumes = [ - "nextcloud-root:/var/www/html" - "nextcloud-apps:/var/www/html/custom_apps" - "nextcloud-config:/var/www/html/config" - "nextcloud-data:/var/www/html/data" - ]; - environment = { - POSTGRES_DB = "nextcloud"; - POSTGRES_USER = "nextcloud"; - POSTGRES_HOST = "localhost"; - OVERWRITEPROTOCOL = "https"; - TRUSTED_PROXIES = "127.0.0.1"; - }; + package = nextcloud; + enable = true; + maxUploadSize = "2G"; + https = true; + + config = { + overwriteProtocol = "https"; + + dbtype = "pgsql"; + dbhost = "/run/postgresql"; + + adminuser = "tlater"; + adminpassFile = config.sops.secrets."nextcloud/tlater".path; + + defaultPhoneRegion = "AT"; + }; + + extraApps = { + # TODO(tlater): Seems like this won't work anymore from + # Nextcloud 25 onwards. + # + # Adopt whatever upstream does with this: + # https://github.com/nextcloud/server/issues/4917 + apporder = pkgs.fetchNextcloudApp { + name = "apporder"; + url = "https://github.com/juliushaertl/apporder/releases/download/v0.15.0/apporder.tar.gz"; + version = "0.15.0"; + sha256 = "sha256-p3VWxTYDCO2NePq6oLM8tBVqYkvoB7itqxp7IZwGDnE="; }; - cron = { - image = "nextcloud:fpm-alpine"; - entrypoint = "/cron.sh"; - dependsOn = ["postgres" "nextcloud"]; - extraOptions = ["--volumes-from=nextcloud-nextcloud"]; + bookmarks = pkgs.fetchNextcloudApp { + name = "bookmarks"; + url = "https://github.com/nextcloud/bookmarks/releases/download/v11.0.4/bookmarks-11.0.4.tar.gz"; + version = "11.0.4"; + sha256 = "sha256-URqtzaCx8FEZHCDP1wSBUFNs+x50jesRtWi+xOU1oXM="; }; - nginx = { - image = "nginx:alpine"; - dependsOn = ["nextcloud"]; - volumes = [ - "nextcloud-root:/var/www/html:ro" - "${./configs/nginx-nextcloud.conf}:/etc/nginx/nginx.conf:ro" - ]; - extraOptions = ["--volumes-from=nextcloud-nextcloud"]; + calendar = pkgs.fetchNextcloudApp { + name = "calendar"; + url = "https://github.com/nextcloud-releases/calendar/releases/download/v3.5.0/calendar-v3.5.0.tar.gz"; + version = "3.5.0"; + sha256 = "sha256-+LRGl9h40AQdWN9SW+NqGwTafAGwV07Af8nVs3pUCm0="; }; - postgres = { - image = "postgres:alpine"; - environment = { - POSTGRES_DB = "nextcloud"; - POSTGRES_USER = "nextcloud"; - }; - volumes = ["nextcloud-postgres-14:/var/lib/postgresql/data"]; + contacts = pkgs.fetchNextcloudApp { + name = "contacts"; + url = "https://github.com/nextcloud-releases/contacts/releases/download/v4.2.2/contacts-v4.2.2.tar.gz"; + version = "4.2.2"; + sha256 = "sha256-GTiyZsUHBXPgQ17DHAihmt2W/ZnAjDwfgwnujkRwk6A="; + }; + + cookbook = pkgs.fetchNextcloudApp { + name = "cookbook"; + url = "https://github.com/nextcloud/cookbook/releases/download/v0.9.15/Cookbook-0.9.15.tar.gz"; + version = "0.9.15"; + sha256 = "sha256-v64rLGyMQOdStyivpJsKrNxwumVQvyK3CnHtZ+K+elE="; + }; + + news = pkgs.fetchNextcloudApp { + name = "news"; + url = "https://github.com/nextcloud/news/releases/download/18.2.0/news.tar.gz"; + version = "18.2.0"; + sha256 = "sha256-eS0cFwJmYfGGJmA02AOWO/OXfqfyI71u2GataDj18DE="; + }; + + notes = pkgs.fetchNextcloudApp { + name = "notes"; + url = "https://github.com/nextcloud/notes/releases/download/v4.5.1/notes.tar.gz"; + version = "4.5.1"; + sha256 = "sha256-rd3uVkVtARX4enRAWm1ivV468lboYZnYe7/zsqaHYpk="; }; }; + + # TODO(tlater): Add redis config. This will be much easier + # starting with 22.11, since this will add an `extraOptions` where + # the necessary redis config can go. + }; + + # Ensure that this service doesn't start before postgres is ready + systemd.services.nextcloud-setup.after = ["postgresql.service"]; + + # Set up SSL + services.nginx.virtualHosts."${hostName}" = { + forceSSL = true; + enableACME = true; }; } diff --git a/configuration/services/postgres.nix b/configuration/services/postgres.nix new file mode 100644 index 0000000..6c584bb --- /dev/null +++ b/configuration/services/postgres.nix @@ -0,0 +1,31 @@ +{pkgs, ...}: { + services.postgresql = { + package = pkgs.postgresql_14; + enable = true; + + # Only enable connections via the unix socket, and check with the + # OS to make sure the user matches the database name. + # + # See https://www.postgresql.org/docs/current/auth-pg-hba-conf.html + authentication = '' + local sameuser all peer + ''; + + # Note: The following options with ensure.* are set-only; i.e., + # when permissions/users/databases are removed from these lists, + # that operation needs to be performed manually on the system as + # well. + ensureUsers = [ + { + name = "nextcloud"; + ensurePermissions = { + "DATABASE nextcloud" = "ALL PRIVILEGES"; + }; + } + ]; + + ensureDatabases = [ + "nextcloud" + ]; + }; +} diff --git a/configuration/services/webserver.nix b/configuration/services/webserver.nix index 093da3d..4a8bee4 100644 --- a/configuration/services/webserver.nix +++ b/configuration/services/webserver.nix @@ -1,47 +1,26 @@ -{ - config, - pkgs, - ... -}: { - users = { - extraUsers.webserver = { - uid = config.ids.uids.webserver; - group = config.users.extraGroups.webserver.name; - isSystemUser = true; - description = "tlater.net web server user"; +{config, ...}: let + domain = config.services.nginx.domain; +in { + services.tlaternet-webserver = { + enable = true; + listen = { + addr = "127.0.0.1"; + port = 8000; }; - extraGroups.webserver = {gid = config.ids.gids.webserver;}; }; - virtualisation.oci-containers.containers.webserver = { - image = "tlaternet/webserver"; + # Set up SSL + services.nginx.virtualHosts."${domain}" = let + inherit (config.services.tlaternet-webserver.listen) addr port; + in { + serverAliases = ["www.${domain}"]; - imageFile = pkgs.dockerTools.buildImage { - name = "tlaternet/webserver"; - tag = "latest"; - contents = pkgs.tlaternet-webserver.webserver; + forceSSL = true; + enableACME = true; + extraConfig = '' + add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always; + ''; - config = let - uid = toString config.users.extraUsers.webserver.uid; - gid = toString config.users.extraGroups.webserver.gid; - in { - Cmd = ["tlaternet-webserver"]; - Volumes = {"/srv/mail" = {};}; - Env = [ - "ROCKET_PORT=3002" - "ROCKET_TEMPLATE_DIR=${pkgs.tlaternet-templates.templates}/browser/" - ]; - ExposedPorts = {"3002" = {};}; - User = "${uid}:${gid}"; - }; - }; - - ports = ["3002:3002"]; - volumes = ["tlaternet-mail:/srv/mail"]; - extraOptions = [ - "--hostname=tlater.net" - # Rocket 0.4 doesn't support SIGTERM anyway, so SIGKILL is the cleanest exit possible. - "--stop-signal=SIGKILL" - ]; + locations."/".proxyPass = "http://${addr}:${toString port}"; }; } diff --git a/flake.lock b/flake.lock index c6f9923..d144fcb 100644 --- a/flake.lock +++ b/flake.lock @@ -1,119 +1,377 @@ { "nodes": { - "flake-utils": { - "locked": { - "lastModified": 1659877975, - "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "flake-utils_2": { - "locked": { - "lastModified": 1659877975, - "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "naersk": { + "alejandra": { "inputs": { + "fenix": "fenix", + "flakeCompat": "flakeCompat", "nixpkgs": [ "tlaternet-webserver", + "dream2nix", "nixpkgs" ] }, "locked": { - "lastModified": 1632266297, - "narHash": "sha256-J1yeJk6Gud9ef2pEf6aKQemrfg1pVngYDSh+SAY94xk=", - "owner": "nmattia", - "repo": "naersk", - "rev": "ee7edec50b49ab6d69b06d62f1de554efccb1ccd", + "lastModified": 1658427149, + "narHash": "sha256-ToD/1z/q5VHsLMrS2h96vjJoLho59eNRtknOUd19ey8=", + "owner": "kamadorueda", + "repo": "alejandra", + "rev": "f5a22afd2adfb249b4e68e0b33aa1f0fb73fb1be", "type": "github" }, "original": { - "owner": "nmattia", - "repo": "naersk", + "owner": "kamadorueda", + "repo": "alejandra", "type": "github" } }, - "nixos-hardware": { + "crane": { + "flake": false, "locked": { - "lastModified": 1650522846, - "narHash": "sha256-SxWHXRI3qJwswyXAtzsi6PKVY3KLNNnb072KaJthII8=", - "owner": "nixos", - "repo": "nixos-hardware", - "rev": "6b4ebea9093c997c5f275c820e679108de4871ab", + "lastModified": 1661875961, + "narHash": "sha256-f1h/2c6Teeu1ofAHWzrS8TwBPcnN+EEu+z1sRVmMQTk=", + "owner": "ipetkov", + "repo": "crane", + "rev": "d9f394e4e20e97c2a60c3ad82c2b6ef99be19e24", "type": "github" }, "original": { - "owner": "nixos", - "ref": "master", - "repo": "nixos-hardware", + "owner": "ipetkov", + "repo": "crane", "type": "github" } }, + "deploy-rs": { + "inputs": { + "flake-compat": "flake-compat", + "nixpkgs": "nixpkgs", + "utils": "utils" + }, + "locked": { + "lastModified": 1659725433, + "narHash": "sha256-1ZxuK67TL29YLw88vQ18Y2Y6iYg8Jb7I6/HVzmNB6nM=", + "owner": "serokell", + "repo": "deploy-rs", + "rev": "41f15759dd8b638e7b4f299730d94d5aa46ab7eb", + "type": "github" + }, + "original": { + "owner": "serokell", + "repo": "deploy-rs", + "type": "github" + } + }, + "devshell": { + "flake": false, + "locked": { + "lastModified": 1653917170, + "narHash": "sha256-FyxOnEE/V4PNEcMU62ikY4FfYPo349MOhMM97HS0XEo=", + "owner": "numtide", + "repo": "devshell", + "rev": "fc7a3e3adde9bbcab68af6d1e3c6eb738e296a92", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "devshell", + "type": "github" + } + }, + "dream2nix": { + "inputs": { + "alejandra": "alejandra", + "crane": "crane", + "devshell": "devshell", + "flake-utils-pre-commit": "flake-utils-pre-commit", + "gomod2nix": "gomod2nix", + "mach-nix": "mach-nix", + "nixpkgs": "nixpkgs_3", + "poetry2nix": "poetry2nix", + "pre-commit-hooks": "pre-commit-hooks" + }, + "locked": { + "lastModified": 1663323895, + "narHash": "sha256-ZmI9C8HNVz2w3OnB79WR/LIgVEY8tDnR8tEPi3hMiJk=", + "owner": "nix-community", + "repo": "dream2nix", + "rev": "25be741ec92c77b8308ca6a7ab89593fe37b6542", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "dream2nix", + "type": "github" + } + }, + "fenix": { + "inputs": { + "nixpkgs": [ + "tlaternet-webserver", + "dream2nix", + "alejandra", + "nixpkgs" + ], + "rust-analyzer-src": "rust-analyzer-src" + }, + "locked": { + "lastModified": 1657607339, + "narHash": "sha256-HaqoAwlbVVZH2n4P3jN2FFPMpVuhxDy1poNOR7kzODc=", + "owner": "nix-community", + "repo": "fenix", + "rev": "b814c83d9e6aa5a28d0cf356ecfdafb2505ad37d", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "fenix", + "type": "github" + } + }, + "fenix_2": { + "inputs": { + "nixpkgs": [ + "tlaternet-webserver", + "nixpkgs" + ], + "rust-analyzer-src": "rust-analyzer-src_2" + }, + "locked": { + "lastModified": 1663396212, + "narHash": "sha256-dlK10QPTDYNpJ/vl2QPKOTrqEbQwAR/v2f4+xsetTkw=", + "owner": "nix-community", + "repo": "fenix", + "rev": "263cd7f991c07a9592a6e825bfc37b23b00eb244", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "fenix", + "type": "github" + } + }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1648199409, + "narHash": "sha256-JwPKdC2PoVBkG6E+eWw3j6BMR6sL3COpYWfif7RVb8Y=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "64a525ee38886ab9028e6f61790de0832aa3ef03", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-utils-pre-commit": { + "locked": { + "lastModified": 1644229661, + "narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flakeCompat": { + "flake": false, + "locked": { + "lastModified": 1650374568, + "narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "b4a34015c698c7793d592d66adbab377907a2be8", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "gomod2nix": { + "flake": false, + "locked": { + "lastModified": 1627572165, + "narHash": "sha256-MFpwnkvQpauj799b4QTBJQFEddbD02+Ln5k92QyHOSk=", + "owner": "tweag", + "repo": "gomod2nix", + "rev": "67f22dd738d092c6ba88e420350ada0ed4992ae8", + "type": "github" + }, + "original": { + "owner": "tweag", + "repo": "gomod2nix", + "type": "github" + } + }, + "mach-nix": { + "flake": false, + "locked": { + "lastModified": 1634711045, + "narHash": "sha256-m5A2Ty88NChLyFhXucECj6+AuiMZPHXNbw+9Kcs7F6Y=", + "owner": "DavHau", + "repo": "mach-nix", + "rev": "4433f74a97b94b596fa6cd9b9c0402104aceef5d", + "type": "github" + }, + "original": { + "id": "mach-nix", + "type": "indirect" + } + }, "nixpkgs": { "locked": { - "lastModified": 1650501692, - "narHash": "sha256-ApKf0/dc0SyB7zZ6yiiOQgcXAhCXxbSDyihHfRDIzx0=", + "lastModified": 1648219316, + "narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "30d3d79b7d3607d56546dd2a6b49e156ba0ec634", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-22_05": { + "locked": { + "lastModified": 1665279158, + "narHash": "sha256-TpbWNzoJ5RaZ302dzvjY2o//WxtOJuYT3CnDj5N69Hs=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "b3783bcfb8ec54e0de26feccfc6cc36b8e202ed5", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "release-22.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1665466769, + "narHash": "sha256-L+qcHpb4Ac3PipMXJY/Ktbu1+KXy23WCZ8pXWmsf7zY=", "owner": "nixos", "repo": "nixpkgs", - "rev": "9887f024766aa27704d1f89f623efd1d063da92a", + "rev": "0b20bf89e0035b6d62ad58f9db8fdbc99c2b01e8", "type": "github" }, "original": { "owner": "nixos", - "ref": "nixos-21.11", + "ref": "nixos-22.05", "repo": "nixpkgs", "type": "github" } }, + "nixpkgs_3": { + "locked": { + "lastModified": 1657638268, + "narHash": "sha256-blBNtQSslAFkg0Gym9fWNJk+bPxGSZib4SOcPrmTPi4=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "d80993b5f885515254746ba6d1917276ee386149", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-unstable", + "type": "indirect" + } + }, + "poetry2nix": { + "flake": false, + "locked": { + "lastModified": 1632969109, + "narHash": "sha256-jPDclkkiAy5m2gGLBlKgH+lQtbF7tL4XxBrbSzw+Ioc=", + "owner": "nix-community", + "repo": "poetry2nix", + "rev": "aee8f04296c39d88155e05d25cfc59dfdd41cc77", + "type": "github" + }, + "original": { + "owner": "nix-community", + "ref": "1.21.0", + "repo": "poetry2nix", + "type": "github" + } + }, + "pre-commit-hooks": { + "inputs": { + "flake-utils": [ + "tlaternet-webserver", + "dream2nix", + "flake-utils-pre-commit" + ], + "nixpkgs": [ + "tlaternet-webserver", + "dream2nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1646153636, + "narHash": "sha256-AlWHMzK+xJ1mG267FdT8dCq/HvLCA6jwmx2ZUy5O8tY=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "b6bc0b21e1617e2b07d8205e7fae7224036dfa4b", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, "root": { "inputs": { - "nixos-hardware": "nixos-hardware", - "nixpkgs": "nixpkgs", + "deploy-rs": "deploy-rs", + "nixpkgs": "nixpkgs_2", "sops-nix": "sops-nix", - "tlaternet-templates": "tlaternet-templates", "tlaternet-webserver": "tlaternet-webserver" } }, - "rust-overlay": { - "inputs": { - "flake-utils": [ - "tlaternet-webserver", - "flake-utils" - ], - "nixpkgs": [ - "tlaternet-webserver", - "nixpkgs" - ] - }, + "rust-analyzer-src": { + "flake": false, "locked": { - "lastModified": 1633400100, - "narHash": "sha256-kHQV7jZ2vVHVI9sfda1mUROVBbQbdfKcbIpKG9WdqGo=", - "owner": "oxalica", - "repo": "rust-overlay", - "rev": "9c2fc6a62ccbc6f420d71ecac6bf0b84dbbee64f", + "lastModified": 1657557289, + "narHash": "sha256-PRW+nUwuqNTRAEa83SfX+7g+g8nQ+2MMbasQ9nt6+UM=", + "owner": "rust-lang", + "repo": "rust-analyzer", + "rev": "caf23f29144b371035b864a1017dbc32573ad56d", "type": "github" }, "original": { - "owner": "oxalica", - "repo": "rust-overlay", + "owner": "rust-lang", + "ref": "nightly", + "repo": "rust-analyzer", + "type": "github" + } + }, + "rust-analyzer-src_2": { + "flake": false, + "locked": { + "lastModified": 1662896065, + "narHash": "sha256-1LkSsXzI1JTAmP/GMTz4fTJd8y/tw8R79l96q+h7mu8=", + "owner": "rust-lang", + "repo": "rust-analyzer", + "rev": "2e9f1204ca01c3e20898d4a67c8b84899d394a88", + "type": "github" + }, + "original": { + "owner": "rust-lang", + "ref": "nightly", + "repo": "rust-analyzer", "type": "github" } }, @@ -121,14 +379,15 @@ "inputs": { "nixpkgs": [ "nixpkgs" - ] + ], + "nixpkgs-22_05": "nixpkgs-22_05" }, "locked": { - "lastModified": 1649756291, - "narHash": "sha256-KTll8bCINAzIUGaaMrbn9wb5nfhkXRLgmFrWGR/Dku0=", + "lastModified": 1665289655, + "narHash": "sha256-j1Q9mNBhbzeJykhObiXwEGres9qvP4vH7gxdJ+ihkLI=", "owner": "Mic92", "repo": "sops-nix", - "rev": "c2614c4fe61943b3d280ac1892fcebe6e8eaf8c8", + "rev": "0ce0449e6404c4ff9d1b7bd657794ae5ca54deb3", "type": "github" }, "original": { @@ -137,42 +396,20 @@ "type": "github" } }, - "tlaternet-templates": { - "inputs": { - "flake-utils": "flake-utils", - "nixpkgs": [ - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1633432574, - "narHash": "sha256-IjGaJAQuFIJ1Is9gtHXsryPOnTDE6tlA61PUKuS8dzw=", - "ref": "master", - "rev": "555a2949bdf643c74b535bd0c623d98f99d33628", - "revCount": 61, - "type": "git", - "url": "https://gitea.tlater.net/tlaternet/tlaternet-templates.git" - }, - "original": { - "type": "git", - "url": "https://gitea.tlater.net/tlaternet/tlaternet-templates.git" - } - }, "tlaternet-webserver": { "inputs": { - "flake-utils": "flake-utils_2", - "naersk": "naersk", + "dream2nix": "dream2nix", + "fenix": "fenix_2", "nixpkgs": [ "nixpkgs" - ], - "rust-overlay": "rust-overlay" + ] }, "locked": { - "lastModified": 1633433130, - "narHash": "sha256-jkW+HV8cJvE86gppOEXQl2ke+bDHJ7SAp8eJp8pJ0N8=", + "lastModified": 1665402451, + "narHash": "sha256-zWaEzUJh0WFVoaLQsMoIj2D+QFhUBJw+f+XzoYqw3es=", "ref": "master", - "rev": "1232950c06ae16bf17fb16ac1f5f2231e971936b", - "revCount": 16, + "rev": "6c29bc5db001e75f5ca06fec726369b87d007a03", + "revCount": 47, "type": "git", "url": "https://gitea.tlater.net/tlaternet/tlaternet.git" }, @@ -180,6 +417,21 @@ "type": "git", "url": "https://gitea.tlater.net/tlaternet/tlaternet.git" } + }, + "utils": { + "locked": { + "lastModified": 1648297722, + "narHash": "sha256-W+qlPsiZd8F3XkzXOzAoR+mpFqzm3ekQkJNa+PIh1BQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "0f8662f1319ad6abf89b3380dd2722369fc51ade", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index 5ff0a51..ec91b53 100644 --- a/flake.nix +++ b/flake.nix @@ -2,141 +2,131 @@ description = "tlater.net host configuration"; inputs = { - nixpkgs.url = "github:nixos/nixpkgs/nixos-21.11"; - nixos-hardware.url = "github:nixos/nixos-hardware/master"; + nixpkgs.url = "github:nixos/nixpkgs/nixos-22.05"; + deploy-rs.url = "github:serokell/deploy-rs"; sops-nix = { url = "github:Mic92/sops-nix"; inputs.nixpkgs.follows = "nixpkgs"; }; - tlaternet-webserver = { url = "git+https://gitea.tlater.net/tlaternet/tlaternet.git"; inputs.nixpkgs.follows = "nixpkgs"; }; - tlaternet-templates = { - url = "git+https://gitea.tlater.net/tlaternet/tlaternet-templates.git"; - inputs.nixpkgs.follows = "nixpkgs"; - }; }; outputs = { self, nixpkgs, - nixos-hardware, sops-nix, + deploy-rs, tlaternet-webserver, - tlaternet-templates, }: let system = "x86_64-linux"; - - overlays = [ - (final: prev: { - tlaternet-webserver = - tlaternet-webserver.legacyPackages.${prev.system}.packages; - tlaternet-templates = - tlaternet-templates.legacyPackages.${prev.system}.packages; - local = import ./pkgs { - pkgs = prev; - }; - }) - ]; - - pkgs = import nixpkgs {inherit system overlays;}; - sops-pkgs = sops-nix.packages.${system}; in { - nixosConfigurations = { + ################## + # Configurations # + ################## + nixosConfigurations = let + # Modules that should be generic to all systems + genericModule = {...}: { + imports = [ + # Inject flake dependencies + sops-nix.nixosModules.sops + tlaternet-webserver.nixosModules.default + + # Import actual configuration + (import ./configuration) + ]; + }; + in { + # The actual system definition tlaternet = nixpkgs.lib.nixosSystem { inherit system; - modules = [ - ({modulesPath, ...}: { - imports = [(modulesPath + "/profiles/headless.nix")]; - nixpkgs.overlays = overlays; - }) - (import ./modules) - - (import ./configuration) - (import ./configuration/linode.nix) - (import ./configuration/hardware-configuration.nix) - sops-nix.nixosModules.sops + genericModule + (import ./configuration/hardware-specific/linode) ]; }; + # A qemu VM to test the above with vm = nixpkgs.lib.nixosSystem { inherit system; - modules = [ - ({modulesPath, ...}: { - imports = [(modulesPath + "/profiles/headless.nix")]; - nixpkgs.overlays = overlays; - }) - (import ./modules) - - (import ./configuration) - sops-nix.nixosModules.sops - ({lib, ...}: { - users.users.tlater.password = "insecure"; - - # Disable graphical tty so -curses works - boot.kernelParams = ["nomodeset"]; - - # Sets the base domain for nginx to localhost so that we - # can easily test locally with the VM. - services.nginx.domain = lib.mkOverride 99 "localhost"; - - # Use the staging secrets - sops.defaultSopsFile = lib.mkOverride 99 ./keys/staging.yaml; - - # # Set up VM settings to match real VPS - # virtualisation.memorySize = 3941; - # virtualisation.cores = 2; - }) + genericModule + (import ./configuration/hardware-specific/vm.nix) ]; }; }; + ############################ + # Deployment configuration # + ############################ + deploy.nodes.tlaternet = { + hostname = "tlater.net"; + + profiles.system = { + user = "root"; + path = deploy-rs.lib.${system}.activate.nixos self.nixosConfigurations.tlaternet; + }; + + sshUser = "tlater"; + sshOpts = ["-t" "-p" "2222"]; + fastConnection = true; + # Currently broken, see https://github.com/serokell/deploy-rs/issues/78 + magicRollback = false; + }; + + ######### + # Tests # + ######### + checks = builtins.mapAttrs (system: deployLib: deployLib.deployChecks self.deploy) deploy-rs.lib; + + #################### + # Helper functions # + #################### + lib = import ./lib {lib = nixpkgs.lib;}; + + #################### + # VM launch script # + #################### apps.${system}.default = let inherit (self.nixosConfigurations.vm.config.system.build) vm; inherit (nixpkgs.legacyPackages.${system}) writeShellScript; - inherit (nixpkgs.lib.attrsets) mapAttrsToList; - inherit (nixpkgs.lib.strings) concatStringsSep; - ports = { + qemuNetOpts = self.lib.makeQemuNetOpts { "2222" = "2222"; "3080" = "80"; "3443" = "443"; - "2221" = "2221"; "21025" = "21025"; # Starbound }; - QEMU_NET_OPTS = - concatStringsSep "," - (mapAttrsToList - (host: vm: "hostfwd=::${host}-:${vm}") - ports); in { type = "app"; program = builtins.toString (writeShellScript "run-vm" '' - export QEMU_OPTS="-m 3941 -smp 2 -curses" - export QEMU_NET_OPTS="${QEMU_NET_OPTS}" + export QEMU_OPTS="-m 3941 -smp 2 -display curses" + export QEMU_NET_OPTS="${qemuNetOpts}" "${vm}/bin/run-tlaternet-vm" ''); }; - devShells.${system}.default = pkgs.mkShell { - sopsPGPKeyDirs = ["./keys/hosts/" "./keys/users/"]; - nativeBuildInputs = [ - sops-pkgs.sops-import-keys-hook - ]; - buildInputs = with pkgs; [ - nixfmt - git-lfs - sops-pkgs.sops-init-gpg-key - ]; + ########################### + # Development environment # + ########################### + devShells.${system}.default = let + inherit (sops-nix.packages.${system}) sops-import-keys-hook sops-init-gpg-key; + deploy-rs-bin = deploy-rs.packages.${system}.default; + pkgs = nixpkgs.legacyPackages.${system}; + in + nixpkgs.legacyPackages.${system}.mkShell { + sopsPGPKeyDirs = ["./keys/hosts/" "./keys/users/"]; + nativeBuildInputs = [ + sops-import-keys-hook + ]; - shellHook = '' - # Work around sudo requiring a full terminal when deploying to - # a remote host - export NIX_SSHOPTS="-t" - ''; - }; + packages = with pkgs; [ + nixfmt + git-lfs + sops-init-gpg-key + deploy-rs-bin + ]; + }; }; } diff --git a/lib/default.nix b/lib/default.nix new file mode 100644 index 0000000..20d874d --- /dev/null +++ b/lib/default.nix @@ -0,0 +1,10 @@ +{lib}: let + inherit (lib.attrsets) mapAttrsToList; + inherit (lib.strings) concatStringsSep; +in { + makeQemuNetOpts = portMapping: + concatStringsSep "," + (mapAttrsToList + (host: vm: "hostfwd=::${host}-:${vm}") + portMapping); +} diff --git a/modules/virtualisation/pods.nix b/modules/virtualisation/pods.nix deleted file mode 100644 index 5a96cc8..0000000 --- a/modules/virtualisation/pods.nix +++ /dev/null @@ -1,222 +0,0 @@ -{ - lib, - config, - options, - ... -}: -with lib; let - cfg = config.virtualisation.pods; - list-to-args = arg: list: - concatStringsSep " " (map (e: "--${arg}=${escapeShellArg e}") list); - possibly-unset-arg = arg: val: (optionalString (val != null) "--${arg}=${escapeShellArg val}"); - - mkPod = name: pod: rec { - path = [config.virtualisation.podman.package]; - - wants = ["network.target"]; - after = ["network-online.target"]; - wantedBy = ["multi-user.target" "default.target"]; - - environment.PODMAN_SYSTEMD_UNIT = "%n"; - - preStart = concatStringsSep " " [ - "mkdir -p /run/podman/pods/ ;" - "podman pod create" - "--infra-conmon-pidfile=${escapeShellArg "/run/podman/pods/${name}.pid"}" - "--name=${escapeShellArg name}" - "--replace" - (list-to-args "add-host" pod.added-hosts) - (possibly-unset-arg "cgroup-parent" pod.cgroup-parent) - (list-to-args "dns" pod.dns) - (list-to-args "dns-opt" pod.dns-opt) - (list-to-args "dns-search" pod.dns-search) - (possibly-unset-arg "hostname" pod.hostname) - (possibly-unset-arg "infra" pod.infra) - (possibly-unset-arg "infra-command" pod.infra-command) - (possibly-unset-arg "infra-image" pod.infra-image) - (possibly-unset-arg "ip" pod.ip) - (possibly-unset-arg "mac-address" pod.mac-address) - (possibly-unset-arg "network" pod.network) - (possibly-unset-arg "network-alias" pod.network-alias) - (possibly-unset-arg "no-hosts" pod.no-hosts) - (list-to-args "publish" pod.publish) - (list-to-args "share" pod.share) - ]; - - script = "podman pod start ${escapeShellArg name}"; - preStop = "podman pod stop ${escapeShellArg name}"; - # `podman generate systemd` generates a second stop after the - # first; not sure why but clearly it's recommended. - postStop = preStop; - - serviceConfig = rec { - Type = "forking"; - TimeoutStopSec = 70; - Restart = "on-failure"; - PIDFile = "/run/podman/pods/${name}.pid"; - }; - }; -in { - options.virtualisation.pods = mkOption { - type = with types; - attrsOf (submodule { - options = { - added-hosts = mkOption { - type = listOf str; - default = []; - description = "Additional hosts to add to /etc/hosts for each container."; - example = literalExample '' - [ "database:10.0.0.1" ] - ''; - }; - - cgroup-parent = mkOption { - type = nullOr str; - default = null; - description = "The cgroups path under which the pod cgroup will be created."; - }; - - dns = mkOption { - type = listOf str; - default = []; - description = "The dns servers to set in /etc/resolv.conf."; - }; - - dns-opt = mkOption { - type = listOf str; - default = []; - description = "dns options to set in /etc/resolv.conf."; - }; - - dns-search = mkOption { - type = listOf str; - default = []; - description = "Search domains to set in /etc/resolv.conf."; - }; - - hostname = mkOption { - type = nullOr str; - default = null; - description = "The pod hostname."; - }; - - infra = mkOption { - type = nullOr bool; - default = null; - description = "Whether to create the infra container for the pod."; - }; - - infra-command = mkOption { - type = nullOr str; - default = null; - description = "The command to run in the infra container."; - }; - - infra-image = mkOption { - type = nullOr str; - default = null; - description = "The image to use for the infra container."; - }; - - ip = mkOption { - type = nullOr str; - default = null; - description = "A static IP address for the pod network."; - }; - - # TODO: set up label file stuff. - # - # labels = mkOption {}; - - mac-address = mkOption { - type = nullOr str; - default = null; - description = "A static mac address for the pod network."; - }; - - network = mkOption { - type = nullOr str; - default = null; - description = "Network configuration for the pod."; - }; - - network-alias = mkOption { - type = nullOr str; - default = null; - description = "DNS alias for the pod."; - }; - - no-hosts = mkOption { - type = nullOr bool; - default = null; - description = "Whether to disable /etc/hosts creation for the pod."; - }; - - publish = mkOption { - type = listOf str; - default = []; - description = "List of ports to publish from the pod."; - }; - - share = mkOption { - type = listOf str; - default = []; - description = "List of kernel namespaces to share."; - }; - - containers = options.virtualisation.oci-containers.containers; - }; - }); - default = {}; - description = "Podman pods to run as systemd services."; - }; - - config = let - # Merge a list of attribute sets together - # - # TODO: See if there's a generic version for this somewhere in the - # pkgs lib? - mergeAttrs = attrList: foldr (a: b: a // b) {} attrList; - - # Create services for all defined pods - pod-services = mapAttrs' (n: v: nameValuePair "pod-${n}" (mkPod n v)) cfg; - - # Override the systemd-specific settings of containers defined in - # pods. - # - # I.e., make a systemd unit dependency on the pod service. - pod-container-services = mergeAttrs (mapAttrsToList (pname: pod: - mapAttrs' (cname: container: - nameValuePair "podman-${pname}-${cname}" rec { - after = ["pod-${pname}.service"]; - requires = after; - }) - pod.containers) - cfg); - - # Override the oci-container settings for containers defined in pods. - # - # I.e., set the --pod=podname setting, and update the dependsOn so - # it points to containers in the same pod. - podifyContainer = container: podname: - container - // { - dependsOn = - map (dependency: "${podname}-${dependency}") container.dependsOn; - extraOptions = container.extraOptions ++ ["--pod=${podname}"]; - }; - in - lib.mkIf (cfg != {}) { - virtualisation.podman.enable = true; - virtualisation.oci-containers.backend = "podman"; - - systemd.services = pod-services // pod-container-services; - - virtualisation.oci-containers.containers = mergeAttrs (mapAttrsToList - (pname: pod: - mapAttrs' (cname: container: - nameValuePair "${pname}-${cname}" (podifyContainer container pname)) - pod.containers) - cfg); - }; -} diff --git a/pkgs/default.nix b/pkgs/default.nix index c92874b..55bf74a 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -1,5 +1,5 @@ {pkgs, ...}: let - inherit (pkgs.lib) callPackage; + inherit (pkgs) callPackage; in { starbound = callPackage ./starbound {}; }