From 5e87a5ec0c5316949d8f80ae4e4fd063c631deba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tristan=20Dani=C3=ABl=20Maat?= Date: Mon, 12 Apr 2021 01:35:24 +0100 Subject: [PATCH 1/5] Start reworking the server for nix flakes This removes all existing services as well, in preparation of moving them to `podman`. These are easier to update to virtualisation.oci-containers while retaining the "networks" through pods. --- .gitattributes | 1 - .gitignore | 2 +- Makefile | 11 - README.md | 55 +--- configuration/default.nix | 57 ++++ .../hardware-configuration.nix | 0 {etc/nixos => configuration}/linode.nix | 4 +- etc/nixos/configuration.nix | 68 ---- etc/nixos/derivations/dist.tar.gz | 3 - etc/nixos/derivations/tlaternet | 1 - etc/nixos/derivations/tlaternet-templates.nix | 15 - .../modules/networked-docker-containers.nix | 306 ------------------ etc/nixos/services/configs/minecraft.tar.gz | 3 - .../services/configs/nginx-nextcloud.conf | 173 ---------- etc/nixos/services/configs/nginx-proxy.conf | 1 - etc/nixos/services/gitea.nix | 51 --- etc/nixos/services/minecraft.nix | 130 -------- etc/nixos/services/nextcloud.nix | 76 ----- etc/nixos/services/nginx.nix | 47 --- etc/nixos/services/tlaternet.nix | 45 --- flake.lock | 60 ++++ flake.nix | 47 +++ {etc/nixos/keys => keys}/tlater.pub | 0 23 files changed, 183 insertions(+), 973 deletions(-) delete mode 100644 .gitattributes delete mode 100644 Makefile create mode 100644 configuration/default.nix rename {etc/nixos => configuration}/hardware-configuration.nix (100%) rename {etc/nixos => configuration}/linode.nix (84%) delete mode 100644 etc/nixos/configuration.nix delete mode 100644 etc/nixos/derivations/dist.tar.gz delete mode 160000 etc/nixos/derivations/tlaternet delete mode 100644 etc/nixos/derivations/tlaternet-templates.nix delete mode 100644 etc/nixos/modules/networked-docker-containers.nix delete mode 100644 etc/nixos/services/configs/minecraft.tar.gz delete mode 100644 etc/nixos/services/configs/nginx-nextcloud.conf delete mode 100644 etc/nixos/services/configs/nginx-proxy.conf delete mode 100644 etc/nixos/services/gitea.nix delete mode 100644 etc/nixos/services/minecraft.nix delete mode 100644 etc/nixos/services/nextcloud.nix delete mode 100644 etc/nixos/services/nginx.nix delete mode 100644 etc/nixos/services/tlaternet.nix create mode 100644 flake.lock create mode 100644 flake.nix rename {etc/nixos/keys => keys}/tlater.pub (100%) diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index f087b42..0000000 --- a/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -*.tar.gz filter=lfs diff=lfs merge=lfs -text diff --git a/.gitignore b/.gitignore index fa9bea6..21e279e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ /result -/tlater.net.qcow2 +/tlaternet.qcow2 diff --git a/Makefile b/Makefile deleted file mode 100644 index f76ef73..0000000 --- a/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -result: etc/nixos/configuration.nix - nix-build '' -A vm -k -I nixos-config=$^ - -tlaternet.qcow2: - nix-shell -p qemu --run 'qemu-img create -f qcow2 $@ 10G' - -run: result tlaternet.qcow2 - QEMU_OPTS="-m 4096 -nographic" QEMU_NET_OPTS="hostfwd=tcp::2222-:2222,hostfwd=tcp::8000-:80,hostfwd=tcp::25565-:25565" ./result/bin/run-tlaternet-vm - -format: $(wildcard etc/nixos/**/*.nix) - nix-shell -p nixpkgs-fmt --run 'nixpkgs-fmt $^' diff --git a/README.md b/README.md index e53ef8c..292a727 100644 --- a/README.md +++ b/README.md @@ -6,51 +6,30 @@ This is the NixOS configuration for [tlater.net](https://tlater.net/). ### Building -To test locally in a VM, [nix](https://nixos.org/nix/) is -required. Using a properly-configured nix, a qemu-based VM running the -server can be created by first applying the following patch to disable -hardware-specific configuration: - -```patch -diff --git a/etc/nixos/configuration.nix b/etc/nixos/configuration.nix -index 387113d..aabee88 100644 ---- a/etc/nixos/configuration.nix -+++ b/etc/nixos/configuration.nix -@@ -2,8 +2,8 @@ - - { - imports = [ -- ./hardware-configuration.nix -- ./linode.nix -+ # ./hardware-configuration.nix -+ # ./linode.nix - ]; - - networking = { -``` - -Then building the VM with: +Build the VM with: ``` -nix-build '' -A vm -k -I nixos-config=./configuration.nix +nixos-rebuild build-vm --flake '.#vm' ``` ### Running -To invoke the VM, use: +Running should *mostly* be as simple as running the command the build +script echos. -``` -QEMU_NET_OPTS="hostfwd=tcp::2222-:2222,hostfwd=tcp::8000-:80" ./result/bin/run-tlater.net-vm +One caveat: create a larger disk image first. This can be done by +running the following in the repository root: + +```bash +qemu-img create -f qcow2 ./tlaternet.qcow2 20G ``` -This will set up a qemu VM with ports 2222 linked to the ssh port, and -8000 to the http port. If other ports are required, adjust the -environment variable (notably, ssl is provided by the image, although -it should not work since it is unlikely that letsencrypt will supply -any certificates). +Everything else should be handled by the devShell. -Note that other environment variables are available (such as one for -disabling the qt GUI, probably handy for eventual CI). They are listed -under "Building a service as a VM (for testing)" -[here](https://nixos.wiki/wiki/Cheatsheet) (not linked since the page -isn't set up very nicely). +### New services + +Whenever a new service is added, append an appropriate +`,hostfwd=::3:` to the `QEMU_NET_OPTS` specified in +`flake.nix` to bind the service to a host port. + +There is no way to test this without binding to the host port, sadly. diff --git a/configuration/default.nix b/configuration/default.nix new file mode 100644 index 0000000..d504e19 --- /dev/null +++ b/configuration/default.nix @@ -0,0 +1,57 @@ +{ config, pkgs, ... }: + +{ + imports = [ ]; + + nix = { + package = pkgs.nixFlakes; + extraOptions = '' + experimental-features = nix-command flakes + ''; + }; + + networking = { + hostName = "tlaternet"; + + usePredictableInterfaceNames = false; + useDHCP = false; + interfaces.eth0.useDHCP = true; + + firewall.allowedTCPPorts = [ 80 443 2222 2221 25565 ]; + }; + + time.timeZone = "Europe/London"; + + users.users.tlater = { + isNormalUser = true; + extraGroups = [ "wheel" ]; + openssh.authorizedKeys.keyFiles = [ ../keys/tlater.pub ]; + }; + + services.openssh = { + enable = true; + allowSFTP = false; + passwordAuthentication = false; + permitRootLogin = "no"; + ports = [ 2222 ]; + startWhenNeeded = true; + }; + + services.nginx = { + enable = true; + recommendedTlsSettings = true; + recommendedOptimisation = true; + recommendedGzipSettings = true; + recommendedProxySettings = true; + clientMaxBodySize = "10G"; + }; + + security.acme = { + email = "tm@tlater.net"; + acceptTerms = true; + }; + + virtualisation.oci-containers.backend = "podman"; + + system.stateVersion = "20.09"; +} diff --git a/etc/nixos/hardware-configuration.nix b/configuration/hardware-configuration.nix similarity index 100% rename from etc/nixos/hardware-configuration.nix rename to configuration/hardware-configuration.nix diff --git a/etc/nixos/linode.nix b/configuration/linode.nix similarity index 84% rename from etc/nixos/linode.nix rename to configuration/linode.nix index e72cb49..da82d20 100644 --- a/etc/nixos/linode.nix +++ b/configuration/linode.nix @@ -2,9 +2,7 @@ { # Required for the lish console - boot = { - kernelParams = [ "console=ttyS0,19200n8" ]; - }; + boot.kernelParams = [ "console=ttyS0,19200n8" ]; boot.loader = { # Timeout to allow lish to connect diff --git a/etc/nixos/configuration.nix b/etc/nixos/configuration.nix deleted file mode 100644 index 4d5e5f9..0000000 --- a/etc/nixos/configuration.nix +++ /dev/null @@ -1,68 +0,0 @@ -{ config, pkgs, ... }: - -{ - imports = [ - ./hardware-configuration.nix - ./linode.nix - - - ./modules/networked-docker-containers.nix - - # FIXME: It'd be much nicer if these were imported further down, - # and set inside the docker-containers set, instead of setting the - # docker-containers set here. - ./services/nginx.nix - ./services/gitea.nix - ./services/nextcloud.nix - ./services/tlaternet.nix - ./services/minecraft.nix - ]; - - networking = { - hostName = "tlaternet"; - - usePredictableInterfaceNames = false; - # useDHCP is deprecated - useDHCP = false; - interfaces.eth0.useDHCP = true; - - firewall = { - enable = true; - allowedTCPPorts = [ - 80 - 443 - 2222 - 2221 - 25565 - ]; - }; - }; - - time.timeZone = "Europe/London"; - - users.users = { - tlater = { - isNormalUser = true; - extraGroups = [ "wheel" "docker" ]; - openssh.authorizedKeys.keyFiles = [ ./keys/tlater.pub ]; - }; - }; - - services = { - openssh = { - enable = true; - allowSFTP = false; - passwordAuthentication = false; - permitRootLogin = "no"; - ports = [ 2222 ]; - startWhenNeeded = true; - }; - }; - - virtualisation.docker = { - enable = true; - autoPrune.enable = true; - }; - - system.stateVersion = "19.09"; -} diff --git a/etc/nixos/derivations/dist.tar.gz b/etc/nixos/derivations/dist.tar.gz deleted file mode 100644 index 3af5e0f..0000000 --- a/etc/nixos/derivations/dist.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1abd2b09bb63554cd6d49d774774cbfb4a933827ceeba373f04bdfbf992a7e5f -size 11858678 diff --git a/etc/nixos/derivations/tlaternet b/etc/nixos/derivations/tlaternet deleted file mode 160000 index 114a878..0000000 --- a/etc/nixos/derivations/tlaternet +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 114a87885e1b3852c4cf6fe9854c86045770b3e4 diff --git a/etc/nixos/derivations/tlaternet-templates.nix b/etc/nixos/derivations/tlaternet-templates.nix deleted file mode 100644 index dbcf050..0000000 --- a/etc/nixos/derivations/tlaternet-templates.nix +++ /dev/null @@ -1,15 +0,0 @@ -{ pkgs ? import {} }: - -with pkgs; - -# TODO: Once https://github.com/svanderburg/node2nix/issues/184 is -# fixed, use a proper nixos package instead of a tarball. -stdenv.mkDerivation { - pname = "tlaternet-templates"; - version = "1.0"; - src = ./dist.tar.gz; - installPhase = '' - mkdir -p $out/srv/ - mv browser $out/srv/web - ''; -} diff --git a/etc/nixos/modules/networked-docker-containers.nix b/etc/nixos/modules/networked-docker-containers.nix deleted file mode 100644 index 2762c8e..0000000 --- a/etc/nixos/modules/networked-docker-containers.nix +++ /dev/null @@ -1,306 +0,0 @@ -{ config, lib, pkgs, ... }: - -with lib; -let - cfg = config.networked-docker-containers; - - networkedDockerContainer = - { ... }: { - - options = { - - image = mkOption { - type = with types; str; - description = "Docker image to run."; - example = "library/hello-world"; - }; - - imageFile = mkOption { - type = with types; nullOr package; - default = null; - description = '' - Path to an image file to load instead of pulling from a registry. - If defined, do not pull from registry. - - You still need to set the image attribute, as it - will be used as the image name for docker to start a container. - ''; - example = literalExample "pkgs.dockerTools.buildDockerImage {...};"; - }; - - cmd = mkOption { - type = with types; listOf str; - default = []; - description = "Commandline arguments to pass to the image's entrypoint."; - example = literalExample '' - ["--port=9000"] - ''; - }; - - entrypoint = mkOption { - type = with types; nullOr str; - description = "Overwrite the default entrypoint of the image."; - default = null; - example = "/bin/my-app"; - }; - - environment = mkOption { - type = with types; attrsOf str; - default = {}; - description = "Environment variables to set for this container."; - example = literalExample '' - { - DATABASE_HOST = "db.example.com"; - DATABASE_PORT = "3306"; - } - ''; - }; - - log-driver = mkOption { - type = types.str; - default = "none"; - description = '' - Logging driver for the container. The default of - "none" means that the container's logs will be - handled as part of the systemd unit. Setting this to - "journald" will result in duplicate logging, but - the container's logs will be visible to the docker - logs command. - - For more details and a full list of logging drivers, refer to the - - Docker engine documentation - ''; - }; - - networks = mkOption { - type = with types; listOf str; - default = []; - description = '' - Docker networks to create and connect this container to. - - The first network in this list will be connected with - --network=, others after container - creation with docker network connect. - - Any networks will be created if they do not exist before - the container is started. - ''; - }; - - ports = mkOption { - type = with types; listOf str; - default = []; - description = '' - Network ports to publish from the container to the outer host. - - Valid formats: - - - - - <ip>:<hostPort>:<containerPort> - - - - - <ip>::<containerPort> - - - - - <hostPort>:<containerPort> - - - - - <containerPort> - - - - - Both hostPort and - containerPort can be specified as a range of - ports. When specifying ranges for both, the number of container - ports in the range must match the number of host ports in the - range. Example: 1234-1236:1234-1236/tcp - - When specifying a range for hostPort only, the - containerPort must not be a - range. In this case, the container port is published somewhere - within the specified hostPort range. Example: - 1234-1236:1234/tcp - - Refer to the - - Docker engine documentation for full details. - ''; - example = literalExample '' - [ - "8080:9000" - ] - ''; - }; - - user = mkOption { - type = with types; nullOr str; - default = null; - description = '' - Override the username or UID (and optionally groupname or GID) used - in the container. - ''; - example = "nobody:nogroup"; - }; - - volumes = mkOption { - type = with types; listOf str; - default = []; - description = '' - List of volumes to attach to this container. - - Note that this is a list of "src:dst" strings to - allow for src to refer to - /nix/store paths, which would difficult with an - attribute set. There are also a variety of mount options available - as a third field; please refer to the - - docker engine documentation for details. - ''; - example = literalExample '' - [ - "volume_name:/path/inside/container" - "/path/on/host:/path/inside/container" - ] - ''; - }; - - workdir = mkOption { - type = with types; nullOr str; - default = null; - description = "Override the default working directory for the container."; - example = "/var/lib/hello_world"; - }; - - dependsOn = mkOption { - type = with types; listOf str; - default = []; - description = '' - Define which other containers this one depends on. They will be added to both After and Requires for the unit. - - Use the same name as the attribute under services.docker-containers. - ''; - example = literalExample '' - services.docker-containers = { - node1 = {}; - node2 = { - dependsOn = [ "node1" ]; - } - } - ''; - }; - - extraDockerOptions = mkOption { - type = with types; listOf str; - default = []; - description = "Extra options for docker run."; - example = literalExample '' - ["--network=host"] - ''; - }; - }; - }; - - mkService = name: container: let - mkAfter = map (x: "docker-${x}.service") container.dependsOn; - in - rec { - wantedBy = [ "multi-user.target" ]; - after = [ "docker.service" "docker.socket" "docker-networks.service" ] ++ mkAfter; - requires = after; - - serviceConfig = { - ExecStart = [ "${pkgs.docker}/bin/docker start -a ${name}" ]; - - ExecStartPre = [ - "-${pkgs.docker}/bin/docker rm -f ${name}" - "-${pkgs.docker}/bin/docker image prune -f" - ] ++ ( - optional (container.imageFile != null) - [ "${pkgs.docker}/bin/docker load -i ${container.imageFile}" ] - ) ++ [ - ( - concatStringsSep " \\\n " ( - [ - "${pkgs.docker}/bin/docker create" - "--rm" - "--name=${name}" - "--log-driver=${container.log-driver}" - ] ++ optional (container.entrypoint != null) - "--entrypoint=${escapeShellArg container.entrypoint}" - ++ (mapAttrsToList (k: v: "-e ${escapeShellArg k}=${escapeShellArg v}") container.environment) - ++ map (p: "-p ${escapeShellArg p}") container.ports - ++ optional (container.user != null) "-u ${escapeShellArg container.user}" - ++ map (v: "-v ${escapeShellArg v}") container.volumes - ++ optional (container.workdir != null) "-w ${escapeShellArg container.workdir}" - ++ optional (container.networks != []) "--network=${escapeShellArg (builtins.head container.networks)}" - ++ map escapeShellArg container.extraDockerOptions - ++ [ container.image ] - ++ map escapeShellArg container.cmd - ) - ) - ] ++ map (n: "${pkgs.docker}/bin/docker network connect ${escapeShellArg n} ${name}") (drop 1 container.networks); - - ExecStop = ''${pkgs.bash}/bin/sh -c "[ $SERVICE_RESULT = success ] || ${pkgs.docker}/bin/docker stop ${name}"''; - ExecStopPost = "-${pkgs.docker}/bin/docker rm -f ${name}"; - - ### There is no generalized way of supporting `reload` for docker - ### containers. Some containers may respond well to SIGHUP sent to their - ### init process, but it is not guaranteed; some apps have other reload - ### mechanisms, some don't have a reload signal at all, and some docker - ### images just have broken signal handling. The best compromise in this - ### case is probably to leave ExecReload undefined, so `systemctl reload` - ### will at least result in an error instead of potentially undefined - ### behaviour. - ### - ### Advanced users can still override this part of the unit to implement - ### a custom reload handler, since the result of all this is a normal - ### systemd service from the perspective of the NixOS module system. - ### - # ExecReload = ...; - ### - - TimeoutStartSec = 0; - TimeoutStopSec = 120; - Restart = "no"; - }; - }; - -in -{ - - options.networked-docker-containers = mkOption { - default = {}; - type = types.attrsOf (types.submodule networkedDockerContainer); - description = "Docker containers to run as systemd services."; - }; - - config = mkIf (cfg != {}) { - - systemd.services = mapAttrs' (n: v: nameValuePair "docker-${n}" (mkService n v)) cfg // { - "docker-networks" = rec { - after = [ "docker.service" "docker.socket" ]; - requires = after; - - serviceConfig = { - Type = "oneshot"; - ExecStart = map ( - n: ''${pkgs.bash}/bin/sh -c "${pkgs.docker}/bin/docker network inspect ${escapeShellArg n} > /dev/null || \ - ${pkgs.docker}/bin/docker network create ${escapeShellArg n}"'' - ) (unique (flatten (mapAttrsToList (_: c: c.networks) cfg))); - }; - }; - }; - - virtualisation.docker.enable = true; - }; -} diff --git a/etc/nixos/services/configs/minecraft.tar.gz b/etc/nixos/services/configs/minecraft.tar.gz deleted file mode 100644 index c8de1ed..0000000 --- a/etc/nixos/services/configs/minecraft.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c0c4cb989a487da07a1ca469b370e1d7ab17a6a13c087871611b6cc8bf5684f6 -size 147313790 diff --git a/etc/nixos/services/configs/nginx-nextcloud.conf b/etc/nixos/services/configs/nginx-nextcloud.conf deleted file mode 100644 index 6594ce9..0000000 --- a/etc/nixos/services/configs/nginx-nextcloud.conf +++ /dev/null @@ -1,173 +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; - - set_real_ip_from 10.0.0.0/8; - set_real_ip_from 172.16.0.0/12; - set_real_ip_from 192.168.0.0/16; - real_ip_header X-Real-IP; - - #gzip on; - - upstream php-handler { - server nextcloud:9000; - } - - server { - listen 80; - - # Add headers to serve security related headers - # Before enabling Strict-Transport-Security headers please read into this - # topic first. - #add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always; - # - # 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 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; - - location = /robots.txt { - allow all; - log_not_found off; - access_log off; - } - - # The following 2 rules are only needed for the user_webfinger app. - # Uncomment it if you're planning to use this app. - #rewrite ^/.well-known/host-meta /public.php?service=host-meta last; - #rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json last; - - # The following rule is only needed for the Social app. - # Uncomment it if you're planning to use this app. - #rewrite ^/.well-known/webfinger /public.php?service=webfinger last; - - location = /.well-known/carddav { - return 301 $scheme://$host:$server_port/remote.php/dav; - } - - location = /.well-known/caldav { - return 301 $scheme://$host:$server_port/remote.php/dav; - } - - # 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; - - # Uncomment if your server is build with the ngx_pagespeed module - # This module is currently not supported. - #pagespeed off; - - location / { - rewrite ^ /index.php; - } - - location ~ ^\/(?:build|tests|config|lib|3rdparty|templates|data)\/ { - deny all; - } - location ~ ^\/(?:\.|autotest|occ|issue|indie|db_|console) { - deny all; - } - - location ~ ^\/(?:index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+)\.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; - - # Avoid sending the security headers twice - fastcgi_param modHeadersAvailable true; - - # Enable pretty urls - fastcgi_param front_controller_active true; - fastcgi_pass php-handler; - fastcgi_intercept_errors on; - fastcgi_request_buffering off; - } - - location ~ ^\/(?:updater|oc[ms]-provider)(?:$|\/) { - try_files $uri/ =404; - index index.php; - } - - # Adding the cache control header for js, css and map files - # Make sure it is BELOW the PHP block - location ~ \.(?:css|js|woff2?|svg|gif|map)$ { - try_files $uri /index.php$request_uri; - add_header Cache-Control "public, max-age=15778463"; - # Add headers to serve security related headers (It is intended to - # have those duplicated to the ones above) - # Before enabling Strict-Transport-Security headers please read into - # this topic first. - #add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always; - # - # 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 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; - - # Optional: Don't log access to assets - access_log off; - } - - location ~ \.(?:png|html|ttf|ico|jpg|jpeg|bcmap|mp4|webm)$ { - try_files $uri /index.php$request_uri; - # Optional: Don't log access to other assets - access_log off; - } - } -} diff --git a/etc/nixos/services/configs/nginx-proxy.conf b/etc/nixos/services/configs/nginx-proxy.conf deleted file mode 100644 index 975735b..0000000 --- a/etc/nixos/services/configs/nginx-proxy.conf +++ /dev/null @@ -1 +0,0 @@ -client_max_body_size 16G; diff --git a/etc/nixos/services/gitea.nix b/etc/nixos/services/gitea.nix deleted file mode 100644 index e4965a4..0000000 --- a/etc/nixos/services/gitea.nix +++ /dev/null @@ -1,51 +0,0 @@ -{ ... }: - -{ - networked-docker-containers = { - gitea = { - image = "gitea/gitea:latest"; - ports = [ - "2221:2221" - ]; - volumes = [ - "gitea:/data:Z" - "/etc/timezone:/etc/timezone:ro" - "/etc/localtime:/etc/localtime:ro" - ]; - environment = { - VIRTUAL_PORT = "3000"; - VIRTUAL_HOST = "gitea.tlater.net"; - LETSENCRYPT_HOST = "gitea.tlater.net"; - - DB_TYPE = "postgres"; - DB_HOST = "gitea-postgres:5432"; - DB_NAME = "gitea"; - DB_USER = "gitea"; - DB_PASSWD = "/qNDDK9WCMuubfA7D8DFwfl9T+Gy2IMDvPhiNpcxZjY="; - - RUN_MODE = "prod"; - DOMAIN = "gitea.tlater.net"; - SSH_PORT = "2221"; - }; - networks = [ - "webproxy" - "gitea" - ]; - }; - - gitea-postgres = { - image = "postgres:alpine"; - environment = { - POSTGRES_DB = "gitea"; - POSTGRES_USER = "gitea"; - POSTGRES_PASSWORD = "/qNDDK9WCMuubfA7D8DFwfl9T+Gy2IMDvPhiNpcxZjY="; - }; - volumes = [ - "gitea-db-data-new:/var/lib/postgresql/data" - ]; - networks = [ - "gitea" - ]; - }; - }; -} diff --git a/etc/nixos/services/minecraft.nix b/etc/nixos/services/minecraft.nix deleted file mode 100644 index 2879335..0000000 --- a/etc/nixos/services/minecraft.nix +++ /dev/null @@ -1,130 +0,0 @@ -{ pkgs, ... }: - -let - entrypoint = pkgs.writeScript "entrypoint.sh" '' - #!${pkgs.bash}/bin/bash - ${pkgs.busybox}/bin/mkdir -p /var/lib/ - ${pkgs.gzip}/bin/gzip -dc ${./configs/minecraft.tar.gz} | ${pkgs.gnutar}/bin/tar -xf - -C /var/lib - echo 'eula=true' > /var/lib/minecraft/eula.txt - ${pkgs.busybox}/bin/cp -f ${properties} /var/lib/minecraft/server.properties - $@ - ''; - ops = pkgs.writeText "ops.json" (builtins.toJSON [ - { - uuid = "140d177a-966f-41b8-a4c0-e305babd291b"; - name = "TLATER"; - level = 4; - bypassesPlayerLimit = true; - } - ]); - whitelist = pkgs.writeText "whitelist.json" (builtins.toJSON [ - { - uuid = "59cd1648-14a4-4bcf-8f5a-2e1bde678f2c"; - name = "romino25"; - } - { - uuid = "0ab6e3d1-544a-47e7-8538-2e6c248e49a4"; - name = "lasi25"; - } - { - uuid = "140d177a-966f-41b8-a4c0-e305babd291b"; - name = "TLATER"; - } - ]); - properties = pkgs.writeText "server.properties" '' - #Minecraft server properties - #Sun Jul 19 16:04:54 GMT 2020 - max-tick-time=60000 - generator-settings= - allow-nether=true - force-gamemode=false - gamemode=0 - enable-query=false - player-idle-timeout=0 - difficulty=1 - spawn-monsters=true - op-permission-level=4 - pvp=false - snooper-enabled=true - level-type=DEFAULT - hardcore=false - enable-command-block=false - max-players=4 - network-compression-threshold=256 - resource-pack-sha1= - max-world-size=29999984 - server-port=25565 - server-ip= - spawn-npcs=true - allow-flight=true - level-name=world - view-distance=15 - resource-pack= - spawn-animals=true - white-list=true - generate-structures=true - online-mode=true - max-build-height=256 - level-seed= - prevent-proxy-connections=false - use-native-transport=true - motd=Adventures met die broers - enable-rcon=false - ''; - -in -{ - docker-containers = { - minecraft = { - image = "tlaternet/minecraft"; - imageFile = pkgs.dockerTools.buildImage { - name = "tlaternet/minecraft"; - tag = "latest"; - config = { - Entrypoint = [ "${entrypoint}" ]; - Cmd = [ "${pkgs.jre}/bin/java" - "-Xms2G" - "-Xmx2G" - # Using recommended flags from https://mcflags.emc.gs - "-XX:+UseG1GC" - "-XX:+ParallelRefProcEnabled" - "-XX:MaxGCPauseMillis=200" - "-XX:+UnlockExperimentalVMOptions" - "-XX:+DisableExplicitGC" - "-XX:+AlwaysPreTouch" - "-XX:G1NewSizePercent=30" - "-XX:G1MaxNewSizePercent=40" - "-XX:G1HeapRegionSize=8M" - "-XX:G1ReservePercent=20" - "-XX:G1HeapWastePercent=5" - "-XX:G1MixedGCCountTarget=4" - "-XX:InitiatingHeapOccupancyPercent=15" - "-XX:G1MixedGCLiveThresholdPercent=90" - "-XX:G1RSetUpdatingPauseTimePercent=5" - "-XX:SurvivorRatio=32" - "-XX:+PerfDisableSharedMem" - "-XX:MaxTenuringThreshold=1" - "-jar" - "/var/lib/minecraft/forge-1.12.2-14.23.5.2854.jar" - "nogui" - ]; - Volumes = { - "/var/lib/minecraft/world" = {}; - }; - WorkingDir = "/var/lib/minecraft"; - ExposedPorts = { - "25565" = {}; - }; - }; - }; - ports = [ - "25565:25565" - ]; - volumes = [ - "minecraft:/var/lib/minecraft/world" - "${ops}:/var/lib/minecraft/ops.json:ro" - "${whitelist}:/var/lib/minecraft/whitelist.json:ro" - ]; - }; - }; -} diff --git a/etc/nixos/services/nextcloud.nix b/etc/nixos/services/nextcloud.nix deleted file mode 100644 index 6fbc2cf..0000000 --- a/etc/nixos/services/nextcloud.nix +++ /dev/null @@ -1,76 +0,0 @@ -{ ... }: - -{ - networked-docker-containers = { - nextcloud = { - image = "nextcloud:fpm-alpine"; - dependsOn = ["nextcloud-postgres"]; - volumes = [ - "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 = "nextcloud-postgres"; - POSTGRES_PASSWORD = "rI7t7Nek1yGA9ucrRc7Uhy0jcjwPjnXa8me4o8tJON8="; - OVERWRITEPROTOCOL = "https"; - }; - networks = [ - "nextcloud" - ]; - extraDockerOptions = [ - "--domainname=nextcloud.tlater.net" - ]; - }; - - nextcloud-cron = { - image = "nextcloud:fpm-alpine"; - entrypoint = "/cron.sh"; - dependsOn = ["nextcloud-postgres"]; - extraDockerOptions = [ - "--volumes-from" - "nextcloud" - ]; - networks = [ - "nextcloud" - ]; - }; - - nextcloud-nginx = { - image = "nginx:alpine"; - dependsOn = ["nextcloud"]; - environment = { - LETSENCRYPT_HOST = "nextcloud.tlater.net"; - VIRTUAL_HOST = "nextcloud.tlater.net"; - }; - volumes = [ - "${./configs/nginx-nextcloud.conf}:/etc/nginx/nginx.conf:ro" - ]; - networks = [ - "webproxy" - "nextcloud" - ]; - extraDockerOptions = [ - "--volumes-from" - "nextcloud" - ]; - }; - - nextcloud-postgres = { - image = "postgres:alpine"; - environment = { - POSTGRES_DB = "nextcloud"; - POSTGRES_USER = "nextcloud"; - POSTGRES_PASSWORD = "rI7t7Nek1yGA9ucrRc7Uhy0jcjwPjnXa8me4o8tJON8="; - }; - volumes = [ - "nextcloud-db-data-new:/var/lib/postgresql/data" - ]; - networks = [ - "nextcloud" - ]; - }; - }; -} diff --git a/etc/nixos/services/nginx.nix b/etc/nixos/services/nginx.nix deleted file mode 100644 index f2daac0..0000000 --- a/etc/nixos/services/nginx.nix +++ /dev/null @@ -1,47 +0,0 @@ -{ ... }: - -{ - networked-docker-containers = { - nginx-proxy = { - image = "jwilder/nginx-proxy:alpine"; - ports = [ - "80:80" - "443:443" - ]; - volumes = [ - "${./configs/nginx-proxy.conf}:/etc/nginx/conf.d/general.conf:ro" - # So that we can watch new containers come up - "/var/run/docker.sock:/tmp/docker.sock:ro" - # So that we can access generated certs - "nginx-certs:/etc/nginx/certs:ro" - # So that we can write challenge files for letsencrypt auth - "nginx-challenges:/usr/share/nginx/html" - # So that we can modify config on-the-fly to set up challenge - # files - "nginx-conf:/etc/nginx/vhost.d" - ]; - environment = { - DHPARAM_GENERATION = "false"; # Provided by nginx-proxy-letsencrypt - }; - networks = [ - "webproxy" - ]; - }; - - nginx-proxy-letsencrypt = { - image = "jrcs/letsencrypt-nginx-proxy-companion"; - dependsOn = ["nginx-proxy"]; - volumes = [ - "/var/run/docker.sock:/var/run/docker.sock:ro" - "nginx-certs:/etc/nginx/certs" - ]; - environment = { - DEFAULT_EMAIL = "tm@tlater.net"; - }; - extraDockerOptions = [ - "--volumes-from" - "nginx-proxy" - ]; - }; - }; -} diff --git a/etc/nixos/services/tlaternet.nix b/etc/nixos/services/tlaternet.nix deleted file mode 100644 index d4e54cb..0000000 --- a/etc/nixos/services/tlaternet.nix +++ /dev/null @@ -1,45 +0,0 @@ -{ pkgs, ... }: - -let - tlaternet = import ../derivations/tlaternet { inherit pkgs; }; - tlaternet-templates = import ../derivations/tlaternet-templates.nix { inherit pkgs; }; - -in -{ - networked-docker-containers = { - web = { - image = "tlaternet/web"; - imageFile = pkgs.dockerTools.buildImage { - name = "tlaternet/web"; - tag = "latest"; - contents = tlaternet; - config = { - Cmd = [ "${tlaternet}/bin/tlaternet" ]; - Volumes = { - "/srv/mail" = {}; - }; - Env = [ - "ROCKET_PORT=80" - "ROCKET_TEMPLATE_DIR=${tlaternet-templates}/srv/web" - ]; - ExposedPorts = { - "80" = {}; - }; - }; - }; - volumes = [ - "tlaternet-mail:/srv/mail" - ]; - environment = { - VIRTUAL_HOST = "tlater.net,www.tlater.net"; - LETSENCRYPT_HOST = "tlater.net,www.tlater.net"; - }; - networks = [ - "webproxy" - ]; - extraDockerOptions = [ - "--domainname=tlater.net" - ]; - }; - }; -} diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..a6faf09 --- /dev/null +++ b/flake.lock @@ -0,0 +1,60 @@ +{ + "nodes": { + "flake-utils": { + "locked": { + "lastModified": 1617631617, + "narHash": "sha256-PARRCz55qN3gy07VJZIlFeOX420d0nGF0RzGI/9hVlw=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b2c27d1a81b0dc266270fa8aeecebbd1807fc610", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixos-hardware": { + "locked": { + "lastModified": 1617690895, + "narHash": "sha256-5TUizPI+ibn/LBzevTIIyIZ1XeLl3HU0PTRk7H6AKTQ=", + "owner": "nixos", + "repo": "nixos-hardware", + "rev": "7c00c8b5cab5dedb6519eabba7ca6d069e2dfdae", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "master", + "repo": "nixos-hardware", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1618149891, + "narHash": "sha256-Sz3DzI1k49Puq+F5KRBsaN3gRXHDzCTG6AwK29Znw0M=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "a7ff7a57c96588fd89370568b72751dd15d24e72", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-20.09", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixos-hardware": "nixos-hardware", + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..212d2fc --- /dev/null +++ b/flake.nix @@ -0,0 +1,47 @@ +{ + description = "tlater.net host configuration"; + + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixos-20.09"; + nixos-hardware.url = "github:nixos/nixos-hardware/master"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = { nixpkgs, nixos-hardware, flake-utils, ... }@inputs: + { + nixosConfigurations = { + tlaternet = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + + modules = [ + (import ./configuration) + (import ./configuration/linode.nix) + (import ./configuration/hardware-configuration.nix) + nixpkgs.modules.headless + ]; + }; + + vm = nixpkgs.lib.nixosSystem { + system = "x86_64-linux"; + + modules = [ + (import ./configuration) + ({ ... }: { + users.users.tlater.password = "insecure"; + # virtualisation.memorySize = 3941; + # virtualisation.cores = 2; + }) + ]; + }; + }; + } // flake-utils.lib.eachDefaultSystem (system: { + devShell = with nixpkgs.legacyPackages.${system}; + mkShell { + buildInputs = [ nixfmt git-lfs ]; + shellHook = '' + export QEMU_OPTS="-m 3941 -smp 2" + export QEMU_NET_OPTS="hostfwd=::3022-:2222,hostfwd=::3080-:80,hostfwd=::3443-:443,hostfwd=::3021-:2221,hostfwd=::25565-:25565" + ''; + }; + }); +} diff --git a/etc/nixos/keys/tlater.pub b/keys/tlater.pub similarity index 100% rename from etc/nixos/keys/tlater.pub rename to keys/tlater.pub -- 2.44.1 From 2df8a6892c33622b671f7f859ce4e62c45c4778c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tristan=20Dani=C3=ABl=20Maat?= Date: Mon, 12 Apr 2021 01:40:19 +0100 Subject: [PATCH 2/5] Implement podman pods option --- flake.nix | 4 + modules/default.nix | 5 + modules/virtualisation/pods.nix | 220 ++++++++++++++++++++++++++++++++ 3 files changed, 229 insertions(+) create mode 100644 modules/default.nix create mode 100644 modules/virtualisation/pods.nix diff --git a/flake.nix b/flake.nix index 212d2fc..a9bba2f 100644 --- a/flake.nix +++ b/flake.nix @@ -14,6 +14,8 @@ system = "x86_64-linux"; modules = [ + (import ./modules) + (import ./configuration) (import ./configuration/linode.nix) (import ./configuration/hardware-configuration.nix) @@ -25,6 +27,8 @@ system = "x86_64-linux"; modules = [ + (import ./modules) + (import ./configuration) ({ ... }: { users.users.tlater.password = "insecure"; diff --git a/modules/default.nix b/modules/default.nix new file mode 100644 index 0000000..0bc1f1c --- /dev/null +++ b/modules/default.nix @@ -0,0 +1,5 @@ +{ ... }: + +{ + imports = [ ./virtualisation/pods.nix ]; +} diff --git a/modules/virtualisation/pods.nix b/modules/virtualisation/pods.nix new file mode 100644 index 0000000..a5c9daa --- /dev/null +++ b/modules/virtualisation/pods.nix @@ -0,0 +1,220 @@ +{ 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); + }; +} -- 2.44.1 From 4689a153b97caa2fab4ff91231826d740090b61e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tristan=20Dani=C3=ABl=20Maat?= Date: Mon, 12 Apr 2021 01:41:31 +0100 Subject: [PATCH 3/5] Add gitea service --- configuration/default.nix | 11 ++++++++- configuration/services/gitea.nix | 38 ++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 configuration/services/gitea.nix diff --git a/configuration/default.nix b/configuration/default.nix index d504e19..de10004 100644 --- a/configuration/default.nix +++ b/configuration/default.nix @@ -1,7 +1,7 @@ { config, pkgs, ... }: { - imports = [ ]; + imports = [ ./services/gitea.nix ]; nix = { package = pkgs.nixFlakes; @@ -44,6 +44,15 @@ recommendedGzipSettings = true; recommendedProxySettings = true; clientMaxBodySize = "10G"; + + virtualHosts = let + host = port: extra: + { + forceSSL = true; + enableACME = true; + locations."/" = { proxyPass = "http://localhost:${toString port}"; }; + } // extra; + in { "gitea.tlater.net" = host 3000 { }; }; }; security.acme = { diff --git a/configuration/services/gitea.nix b/configuration/services/gitea.nix new file mode 100644 index 0000000..0e603df --- /dev/null +++ b/configuration/services/gitea.nix @@ -0,0 +1,38 @@ +{ config, ... }: + +{ + virtualisation.pods.gitea = { + hostname = "gitea.tlater.net"; + publish = [ "3000:3000" "2221:2221" ]; + + containers = { + gitea = { + image = "gitea/gitea:latest"; + volumes = [ "gitea:/data:Z" "/etc/localtime:/etc/localtime:ro" ]; + dependsOn = [ "postgres" ]; + + environment = { + DB_TYPE = "postgres"; + DB_HOST = "gitea-postgres:5432"; + DB_NAME = "gitea"; + DB_USER = "gitea"; + DB_PASSWD = "/qNDDK9WCMuubfA7D8DFwfl9T+Gy2IMDvPhiNpcxZjY="; + + RUN_MODE = "prod"; + DOMAIN = "gitea.tlater.net"; + SSH_PORT = "2221"; + }; + }; + + postgres = { + image = "postgres:alpine"; + environment = { + POSTGRES_DB = "gitea"; + POSTGRES_USER = "gitea"; + POSTGRES_PASSWORD = "/qNDDK9WCMuubfA7D8DFwfl9T+Gy2IMDvPhiNpcxZjY="; + }; + volumes = [ "gitea-db-data-new:/var/lib/postgresql/data" ]; + }; + }; + }; +} -- 2.44.1 From 98cf95a922e613fe4d0be933a8f613222bc2b85c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tristan=20Dani=C3=ABl=20Maat?= Date: Mon, 12 Apr 2021 01:42:46 +0100 Subject: [PATCH 4/5] Add nextcloud service --- configuration/default.nix | 7 +- .../services/configs/nginx-nextcloud.conf | 173 ++++++++++++++++++ configuration/services/nextcloud.nix | 52 ++++++ 3 files changed, 230 insertions(+), 2 deletions(-) create mode 100644 configuration/services/configs/nginx-nextcloud.conf create mode 100644 configuration/services/nextcloud.nix diff --git a/configuration/default.nix b/configuration/default.nix index de10004..3c9b0df 100644 --- a/configuration/default.nix +++ b/configuration/default.nix @@ -1,7 +1,7 @@ { config, pkgs, ... }: { - imports = [ ./services/gitea.nix ]; + imports = [ ./services/gitea.nix ./services/nextcloud.nix ]; nix = { package = pkgs.nixFlakes; @@ -52,7 +52,10 @@ enableACME = true; locations."/" = { proxyPass = "http://localhost:${toString port}"; }; } // extra; - in { "gitea.tlater.net" = host 3000 { }; }; + in { + "gitea.tlater.net" = host 3000 { }; + "nextcloud.tlater.net" = host 3001 { }; + }; }; security.acme = { diff --git a/configuration/services/configs/nginx-nextcloud.conf b/configuration/services/configs/nginx-nextcloud.conf new file mode 100644 index 0000000..3eb1193 --- /dev/null +++ b/configuration/services/configs/nginx-nextcloud.conf @@ -0,0 +1,173 @@ +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; + + set_real_ip_from 10.0.0.0/8; + set_real_ip_from 172.16.0.0/12; + set_real_ip_from 192.168.0.0/16; + real_ip_header X-Real-IP; + + #gzip on; + + upstream php-handler { + server nextcloud-nextcloud:9000; + } + + server { + listen 80; + + # Add headers to serve security related headers + # Before enabling Strict-Transport-Security headers please read into this + # topic first. + #add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always; + # + # 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 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; + + location = /robots.txt { + allow all; + log_not_found off; + access_log off; + } + + # The following 2 rules are only needed for the user_webfinger app. + # Uncomment it if you're planning to use this app. + #rewrite ^/.well-known/host-meta /public.php?service=host-meta last; + #rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json last; + + # The following rule is only needed for the Social app. + # Uncomment it if you're planning to use this app. + #rewrite ^/.well-known/webfinger /public.php?service=webfinger last; + + location = /.well-known/carddav { + return 301 $scheme://$host:$server_port/remote.php/dav; + } + + location = /.well-known/caldav { + return 301 $scheme://$host:$server_port/remote.php/dav; + } + + # 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; + + # Uncomment if your server is build with the ngx_pagespeed module + # This module is currently not supported. + #pagespeed off; + + location / { + rewrite ^ /index.php; + } + + location ~ ^\/(?:build|tests|config|lib|3rdparty|templates|data)\/ { + deny all; + } + location ~ ^\/(?:\.|autotest|occ|issue|indie|db_|console) { + deny all; + } + + location ~ ^\/(?:index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+)\.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; + + # Avoid sending the security headers twice + fastcgi_param modHeadersAvailable true; + + # Enable pretty urls + fastcgi_param front_controller_active true; + fastcgi_pass php-handler; + fastcgi_intercept_errors on; + fastcgi_request_buffering off; + } + + location ~ ^\/(?:updater|oc[ms]-provider)(?:$|\/) { + try_files $uri/ =404; + index index.php; + } + + # Adding the cache control header for js, css and map files + # Make sure it is BELOW the PHP block + location ~ \.(?:css|js|woff2?|svg|gif|map)$ { + try_files $uri /index.php$request_uri; + add_header Cache-Control "public, max-age=15778463"; + # Add headers to serve security related headers (It is intended to + # have those duplicated to the ones above) + # Before enabling Strict-Transport-Security headers please read into + # this topic first. + #add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always; + # + # 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 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; + + # Optional: Don't log access to assets + access_log off; + } + + location ~ \.(?:png|html|ttf|ico|jpg|jpeg|bcmap|mp4|webm)$ { + try_files $uri /index.php$request_uri; + # Optional: Don't log access to other assets + access_log off; + } + } +} diff --git a/configuration/services/nextcloud.nix b/configuration/services/nextcloud.nix new file mode 100644 index 0000000..aeb9fc8 --- /dev/null +++ b/configuration/services/nextcloud.nix @@ -0,0 +1,52 @@ +{ config, ... }: + +{ + virtualisation.pods.nextcloud = { + hostname = "nextcloud.tlater.net"; + publish = [ "3001:80" ]; + + containers = { + nextcloud = { + image = "nextcloud:fpm-alpine"; + dependsOn = [ "postgres" ]; + volumes = [ + "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 = "nextcloud-postgres"; + POSTGRES_PASSWORD = "rI7t7Nek1yGA9ucrRc7Uhy0jcjwPjnXa8me4o8tJON8="; + OVERWRITEPROTOCOL = "https"; + }; + }; + + cron = { + image = "nextcloud:fpm-alpine"; + entrypoint = "/cron.sh"; + dependsOn = [ "postgres" "nextcloud" ]; + extraOptions = [ "--volumes-from=nextcloud-nextcloud" ]; + }; + + nginx = { + image = "nginx:alpine"; + dependsOn = [ "nextcloud" ]; + volumes = + [ "${./configs/nginx-nextcloud.conf}:/etc/nginx/nginx.conf:ro" ]; + extraOptions = [ "--volumes-from=nextcloud-nextcloud" ]; + }; + + postgres = { + image = "postgres:alpine"; + environment = { + POSTGRES_DB = "nextcloud"; + POSTGRES_USER = "nextcloud"; + POSTGRES_PASSWORD = "rI7t7Nek1yGA9ucrRc7Uhy0jcjwPjnXa8me4o8tJON8="; + }; + volumes = [ "nextcloud-db-data-new:/var/lib/postgresql/data" ]; + }; + }; + }; +} -- 2.44.1 From 40002ac76ee2425f0faf72fb438702b10203670c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tristan=20Dani=C3=ABl=20Maat?= Date: Mon, 12 Apr 2021 01:44:10 +0100 Subject: [PATCH 5/5] Add webserver service --- configuration/default.nix | 4 +- configuration/services/webserver.nix | 27 +++++++ flake.lock | 112 ++++++++++++++++++++++++++- flake.nix | 31 +++++++- 4 files changed, 170 insertions(+), 4 deletions(-) create mode 100644 configuration/services/webserver.nix diff --git a/configuration/default.nix b/configuration/default.nix index 3c9b0df..a00235b 100644 --- a/configuration/default.nix +++ b/configuration/default.nix @@ -1,7 +1,8 @@ { config, pkgs, ... }: { - imports = [ ./services/gitea.nix ./services/nextcloud.nix ]; + imports = + [ ./services/gitea.nix ./services/nextcloud.nix ./services/webserver.nix ]; nix = { package = pkgs.nixFlakes; @@ -53,6 +54,7 @@ locations."/" = { proxyPass = "http://localhost:${toString port}"; }; } // extra; in { + "tlater.net" = host 3002 { serverAliases = [ "www.tlater.net" ]; }; "gitea.tlater.net" = host 3000 { }; "nextcloud.tlater.net" = host 3001 { }; }; diff --git a/configuration/services/webserver.nix b/configuration/services/webserver.nix new file mode 100644 index 0000000..1a182e2 --- /dev/null +++ b/configuration/services/webserver.nix @@ -0,0 +1,27 @@ +{ config, pkgs, ... }: + +{ + virtualisation.oci-containers.containers.webserver = { + image = "tlaternet/webserver"; + + imageFile = pkgs.dockerTools.buildImage { + name = "tlaternet/webserver"; + tag = "latest"; + contents = pkgs.tlaternet-webserver.webserver; + + config = { + Cmd = [ "tlaternet-webserver" ]; + Volumes = { "/srv/mail" = { }; }; + Env = [ + "ROCKET_PORT=80" + "ROCKET_TEMPLATE_DIR=${pkgs.tlaternet-templates.templates}/browser/" + ]; + ExposedPorts = { "80" = { }; }; + }; + }; + + ports = [ "3002:80" ]; + volumes = [ "tlaternet-mail:/srv/mail" ]; + extraOptions = [ "--hostname=tlater.net" ]; + }; +} diff --git a/flake.lock b/flake.lock index a6faf09..939bc49 100644 --- a/flake.lock +++ b/flake.lock @@ -15,6 +15,26 @@ "type": "github" } }, + "naersk": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1614785451, + "narHash": "sha256-TPw8kQvr2UNCuvndtY+EjyXp6Q5GEW2l9UafXXh1XmI=", + "owner": "nmattia", + "repo": "naersk", + "rev": "e0fe990b478a66178a58c69cf53daec0478ca6f9", + "type": "github" + }, + "original": { + "owner": "nmattia", + "repo": "naersk", + "type": "github" + } + }, "nixos-hardware": { "locked": { "lastModified": 1617690895, @@ -47,11 +67,101 @@ "type": "github" } }, + "nixpkgs-unstable": { + "locked": { + "lastModified": 1617899217, + "narHash": "sha256-gd5JHH7IkeoIQ/oiGZSqDpGdGt7DMRJTQ8JiD8+hdOQ=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "9e377a6ce42dccd9b624ae4ce8f978dc892ba0e2", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, "root": { "inputs": { "flake-utils": "flake-utils", "nixos-hardware": "nixos-hardware", - "nixpkgs": "nixpkgs" + "nixpkgs": "nixpkgs", + "tlaternet-templates": "tlaternet-templates", + "tlaternet-webserver": "tlaternet-webserver" + } + }, + "rust-overlay": { + "inputs": { + "flake-utils": [ + "flake-utils" + ], + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1617071065, + "narHash": "sha256-9JXhxwlc/ZJaO4aZ3cUwQwlK7ZRamjV+BvOTvdXrggs=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "38766381042021f547a168ebb3f10305dc6fde08", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + }, + "tlaternet-templates": { + "inputs": { + "flake-utils": [ + "flake-utils" + ], + "nixpkgs": [ + "nixpkgs" + ], + "nixpkgs-unstable": "nixpkgs-unstable" + }, + "locked": { + "lastModified": 1618117315, + "narHash": "sha256-RSqbWv20zNDhCx1VARxEjrYH1pNv+H2pY8dQ29tdNjA=", + "ref": "master", + "rev": "6da1d644ac02143172d20e0d3e9fcd7a0c8720ef", + "revCount": 60, + "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" + ], + "naersk": "naersk", + "nixpkgs": [ + "nixpkgs" + ], + "rust-overlay": "rust-overlay" + }, + "locked": { + "lastModified": 1617992257, + "narHash": "sha256-TfcLtS/1Niv21NN5e9VGUbK0fpoOvgmx1caO4LBcTas=", + "ref": "master", + "rev": "ff25f151d3c170c7290b83be5cbdb1fd84261997", + "revCount": 14, + "type": "git", + "url": "https://gitea.tlater.net/tlaternet/tlaternet.git" + }, + "original": { + "type": "git", + "url": "https://gitea.tlater.net/tlaternet/tlaternet.git" } } }, diff --git a/flake.nix b/flake.nix index a9bba2f..5fad4b8 100644 --- a/flake.nix +++ b/flake.nix @@ -5,15 +5,41 @@ nixpkgs.url = "github:nixos/nixpkgs/nixos-20.09"; nixos-hardware.url = "github:nixos/nixos-hardware/master"; flake-utils.url = "github:numtide/flake-utils"; + tlaternet-webserver = { + url = "git+https://gitea.tlater.net/tlaternet/tlaternet.git"; + inputs = { + flake-utils.follows = "flake-utils"; + nixpkgs.follows = "nixpkgs"; + }; + }; + tlaternet-templates = { + url = "git+https://gitea.tlater.net/tlaternet/tlaternet-templates.git"; + inputs = { + flake-utils.follows = "flake-utils"; + nixpkgs.follows = "nixpkgs"; + }; + }; }; - outputs = { nixpkgs, nixos-hardware, flake-utils, ... }@inputs: - { + outputs = { nixpkgs, nixos-hardware, flake-utils, tlaternet-webserver + , tlaternet-templates, ... }@inputs: + let + overlays = [ + (final: prev: { + tlaternet-webserver = + tlaternet-webserver.legacyPackages.${prev.system}.packages; + tlaternet-templates = + tlaternet-templates.legacyPackages.${prev.system}.packages; + }) + ]; + + in { nixosConfigurations = { tlaternet = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; modules = [ + ({ ... }: { nixpkgs.overlays = overlays; }) (import ./modules) (import ./configuration) @@ -27,6 +53,7 @@ system = "x86_64-linux"; modules = [ + ({ ... }: { nixpkgs.overlays = overlays; }) (import ./modules) (import ./configuration) -- 2.44.1