diff --git a/.drone.yml b/.drone.yml index 2478a0c..7713016 100644 --- a/.drone.yml +++ b/.drone.yml @@ -25,7 +25,22 @@ steps: - ./build.sh - '[ "$DRONE_COMMIT_BRANCH" = "master" ] || zola build -u "https://${DRONE_COMMIT}--schulpodcast.netlify.app"' - - name: publish-prod + - name: publish-rsync-prod + image: drillster/drone-rsync + settings: + hosts: [ "static.95.107.181.135.clients.your-server.de" ] + user: deploy + key: + from_secret: deploy_key + source: public/ + target: . # set by rrsync + args: [ "-v" ] + delete: true + when: + branch: + - master + + - name: publish-netlify-prod image: r.sbruder.de/drone-netlify settings: auth_token: @@ -36,7 +51,7 @@ steps: branch: - master - - name: publish-preview + - name: publish-netlify-preview image: r.sbruder.de/drone-netlify settings: auth_token: diff --git a/README.md b/README.md index 40a6bae..c8a66b9 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,8 @@ # schulpodcast (prototype) Prototype for the site of the podcast for the practical seminar podcast. + +## How to deploy + + nixops create deploy.nix + nixops deploy diff --git a/deploy.nix b/deploy.nix new file mode 100644 index 0000000..7a07912 --- /dev/null +++ b/deploy.nix @@ -0,0 +1,111 @@ +let + pkgs = import { }; + stdenv = pkgs.stdenv; +in +{ + network.description = "Web server for schulpodcast"; + + front = + { config, pkgs, ... }: + { + services.nginx = { + enable = true; + + recommendedTlsSettings = true; + recommendedOptimisation = true; + recommendedGzipSettings = true; + + commonHttpConfig = '' + # since default hcloud name used for testing is quite long + server_names_hash_bucket_size 128; + + # privacy-aware log format + log_format custom '$remote_addr_anon - - [$time_local] "$request" $status $body_bytes_sent "-" "$http_user_agent"'; + access_log /var/log/nginx/access.log custom; + + map $remote_addr $remote_addr_anon { + ~(?P\d+\.\d+)\. $ip.0.0; + ~(?P[^:]+:[^:]+): $ip::; + default 0.0.0.0; + } + ''; + + virtualHosts = { + "_" = { + extraConfig = '' + access_log off; + return 404; + ''; + }; + + ${config.deployment.targetHost} = { + enableACME = true; + forceSSL = true; + root = "/var/www/"; + }; + + "www.${config.deployment.targetHost}" = { + globalRedirect = config.deployment.targetHost; + }; + }; + }; + + security.acme = { + acceptTerms = true; + email = "security@sbruder.de"; + }; + + networking = { + firewall.allowedTCPPorts = [ 80 443 ]; + + # static IPv6 config + usePredictableInterfaceNames = false; # required for static config + defaultGateway6 = { address = "fe80::1"; interface = "eth0"; }; + interfaces.eth0.ipv6.addresses = [ + { address = "2a01:4f9:c010:dac3::"; prefixLength = 64; } + ]; + }; + + deployment.targetHost = "static.95.107.181.135.clients.your-server.de"; + + imports = [ + + + + ]; + + services.openssh.enable = true; + users.users = { + root.openssh.authorizedKeys.keys = [ + "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCwMo0mYcTU1Y4BKpEUsvKAtcTPq3ylKaw+ZjUxNg9VqU5gDy2TDUfWk2FjM2VYcqQJ9ZaNGKE1S18fRU7ZHrcgtFPMgAuji87yOKojH74cwz9ZRf5ZiluWBmR3dFd7kddqHUKVS8utpiQuTLIyQwpgmUHA81IasWXuB2pHaI6HGntMlJTm1CvpcQvwKsDBqJ2bFjFMk6EDgAZWXyooQgthYAfmc+YfAX5T9fWKiqFnEJ0ryN3/RngJZe65HWV8WZwY1CxgKQhOZuRcPdkTEQlUk9Qu0JbVa2sTgdYDpw/Dz0ma+h4rxOrH63MD6Cf0pFgOwLeZVSmXqKTjXVaH1QkHWRat88J8Q6MM6LlhLx/48VcQshhIssAZ37YoW2W0NxnGSM7YtlwTVe+w7rU//cS5TyIQa4joq2pnIh4uurbNkIULa4Q2t2nEMzlqI9gEE9DK1ctOcuCyFOerNZD0yRZ5Rs8WouDLL1PR6ps4czK2N7h2MXABcELuVwX+sdxwFgf6AJaRvrlw4qIOohpeX48FhzZfcI9Cqvnakm+O42J3qXuUDVc6/NjE9zBku3dNaeseGv9CQxtvyVDq6o9MRDiFror3yEiN0Fwou7CXBfXrbeb7MvahsRxSKkSDY0uA+AXmsm1UwdArjEcEMsS1JeFQCdX1yR/Z5xzj2gx60NcR4w== simon@nunotaba" + "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC1kQUoPII8A9/bgPA+OrZGQLPA8MxkdmPSCCsfGMh9qRZfF7BSD8W6VdE/28tLw+39QeUl1+/9VuVvGjZBP1zBAbKIcKx4DjtgxpNXCsfWMjXFtpTGk2dyl71CaY5n72YlADxXYwtEvuwfNixgE2yTCefMbBsfwqYC0GZGiDlFtjxdg+RuUC8jU++C+WFUFct9gj9ieQ0LWjud+Oh0AF0JhyGnou+wVZIIO8mwo7Cc5xiPldXhbc13XiNC3mpNGCLFj+nh1feazk8TeAVDBps6xaDkOd+hDwTBQh8LoimePK7MiShzLvC38Vd/sim5ym/IqY634CjqBDGCMp1KXnqHUTT8CqeifMv10+aRJKUPevVkO3nEE3VoSPt7Ui9ZzLnL4qhZyygoBau+PvD2WCWm+gRwBkvU1uNrYKi4HIGhB/gXcYHKJimqJwLMyqG5Wv1jfuhn3ZZN+uNqTgdAznGgPRU1Q/Mx6nMEDiQip78qdYEc0YGwdb/TldEL6aHRjuNuZPpTW+zakQHiQTRb/0VdZT1bAwyT9yL0Uf40h706Kh/pKiSQ1yq1dlSdl3RlfedbqLqGjspds1iRSrSXyH2MBghPbz/SF7Vt4LW/tXF0rcyV7CU98ZvxJDWeN60OE0vPf/AT5udYyfPO1691y0F8jGKxGYYPg9R/Y5o7J24PbQ== simon@sayuri" + ]; + + deploy = { + isSystemUser = true; + shell = "/bin/sh"; + + openssh.authorizedKeys.keys = [ + "command=\"${pkgs.rrsync}/bin/rrsync -wo /var/www/\",no-agent-forwarding,no-port-forwarding,no-pty,no-user-rc,no-X11-forwarding ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC63lDMYNsQ52PSLEWwQSoAyNmoC1ocNSlo3K8LUN60Zr3vbIi46xxKMP4drT5Cg4zc8VdfQZEBitH6Oi3TQu5+MJgXvkNfokhkTpuG299uiTY52DsL+daJvnbo2tbtEfbDJMPhl1W5cHgIjQxZdOOmHYjrLjJctldfH+Uc4o4ZVAKBoVplgm3f7zrwjqRP+GQofKN0+ORlXyNdeoEd9hQFFfUYu3eIAKv7YzSMfjug1LwiSbCU0On0x2K5FviPioC0R7mEwRmyZjBWMCRNwRrDnKuPF5yJ1G2sDoXTIdtiFDGsb57TTqYO2j3kW0QnirSav1RZSryJj/lFYt6EtjVN4Tj3gFar1uZkTOnTmpfqstrv7JFVFctRksmqPXt01ccZk92RNU3flZUoAvN0Dn8P1Elq23FHnhTYOjywo/u3Mmejty02553SBHon6gJo4o4ihHB0MePSieOfrd8ICyXXNNcB5m+B2xjKWqo5ssU0mHQiO2yRtcAMGfvS8hDBWxE=" + ]; + }; + }; + + systemd.tmpfiles.rules = [ + "d /var/www 0755 deploy root -" + ]; + + fileSystems."/" = { + device = "/dev/sda1"; + fsType = "ext4"; + }; + + boot = { + cleanTmpDir = true; + loader = { + grub.device = "/dev/sda"; + timeout = 2; + }; + }; + }; +} diff --git a/shell.nix b/shell.nix index 07668f3..f993d3f 100644 --- a/shell.nix +++ b/shell.nix @@ -1,11 +1,16 @@ -{ pkgs ? import {} }: +{ pkgs ? import { } }: pkgs.mkShell { buildInputs = with pkgs; [ + nixops python38 python38Packages.mutagen zola unzip wget ]; + + shellHook = '' + export NIXOPS_DEPLOYMENT=schulpodcast-hcloud + ''; }