Browse Source

feat: add nixops configuration for apollo hetzner

Signed-off-by: Chinmay D. Pai <chinmaydpai@gmail.com>
master
Chinmay D. Pai 5 months ago
parent
commit
e1a9e5943f
Signed by: thunderbottom GPG Key ID: 75507BE256F40CED
14 changed files with 451 additions and 0 deletions
  1. +2
    -0
      .gitignore
  2. +10
    -0
      nixops/configs/deployment-keys.nix
  3. +4
    -0
      nixops/configs/ssh-keys.nix
  4. +53
    -0
      nixops/hosts/apollo/default.nix
  5. +11
    -0
      nixops/hosts/apollo/system/boot.nix
  6. +16
    -0
      nixops/hosts/apollo/system/nixos.nix
  7. +6
    -0
      nixops/servers/configuration.nix
  8. +50
    -0
      nixops/services/bitwarden.nix
  9. +25
    -0
      nixops/services/blog.nix
  10. +56
    -0
      nixops/services/drone.nix
  11. +72
    -0
      nixops/services/firefly.nix
  12. +90
    -0
      nixops/services/gitea.nix
  13. +27
    -0
      nixops/services/nginx.nix
  14. +29
    -0
      nixops/services/ripe-atlas.nix

+ 2
- 0
.gitignore View File

@ -13,3 +13,5 @@
# .nfs files are created when an open file is removed but is still being accessed
.nfs*
# deployment key secrets for nixops
secrets.nix

+ 10
- 0
nixops/configs/deployment-keys.nix View File

@ -0,0 +1,10 @@
{ config, pkgs, ... }:
let
secrets = import ./secrets.nix;
in {
deployment.keys.gitea-postgres.text = secrets.gitea-postgres-password;
deployment.keys.gitea-postgres.user = "git";
deployment.keys.gitea-postgres.group = "wheel";
deployment.keys.gitea-postgres.permissions = "0640";
}

+ 4
- 0
nixops/configs/ssh-keys.nix View File

@ -0,0 +1,4 @@
{
blog = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG3PeMbehJBkmv8Ee7xJimTzXoSdmAnxhBatHSdS+saM";
chnmy = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCpiOhIJVlxFT/4jod6dLEcumeP+LZ7nxHh3TVhhwPun0/CZ0vF7OiKJMnWt9SKkJuo0cV+JaL40ZEsQNUOSXeYPKLGsIJdqDL0xyZdM+0PN3c2feecIjaf/aUgMvdGHFL23aKZN8+fmF1ooezezexly6g2l6geqStzydYFG8aQuBa3YM1KbZlVjaz+T3tb6jT1lf4o097/r4z596LNdFKazjoKHvmkOyxlwi2H95reUQTd+WP3eZSVhAhoiDHxYcJ8ps6OQlVG5gOsSYj6oy7oZJZk52v34k4WSHbVdhwBApci8pg0VaCE9y00tUjivSeMqBQtSZzH1ygtFp8jHyDJGrVN17PNr2gJyWf4pxia1OW53HzAzocUzxSP6q497HpPlSeh6xbPrrFeKki5K8RQ4ysYmhqWGofEQat5HJMaRicowsGCcQrZ/B7671Fw9Kse5B5mzSo/RSYRh4rDEVtg2Nl+bCG36dACS0bft1uVBRtqDQg8w2P4HIRh2KAlahfzE0Q//U19KvwR6VKPqBoLnMUcITtrzCqanB1WIciadAtDi/1HpeCkSn/UvOC9pl2WzNhPF1WZfxSawc7dSyj+CKEahcPZCu3hgkgD28Bhojv4gEtJv+mM0HTgS7qwZUE1pZpdICR6cvizX+khTAgeKrbi1pfvztqXT9a0weRt7w==";
}

+ 53
- 0
nixops/hosts/apollo/default.nix View File

@ -0,0 +1,53 @@
{ config, lib, pkgs, ... }:
let
auth-keys = with import ../../configs/ssh-keys.nix; [ chnmy ];
in {
imports = [
<nixpkgs/nixos/modules/profiles/qemu-guest.nix>
<nixpkgs/nixos/modules/profiles/hardened.nix>
<nixpkgs/nixos/modules/profiles/headless.nix>
./system/boot.nix
./system/nixos.nix
../../configs/deployment-keys.nix
../../services/bitwarden.nix
../../services/blog.nix
../../services/drone.nix
../../services/firefly.nix
../../services/gitea.nix
../../services/nginx.nix
../../services/ripe-atlas.nix
../../../virtualization/docker.nix
];
deployment.targetHost = "49.12.4.20";
fileSystems."/" = {
device = "/dev/sda1";
fsType = "ext4";
};
networking.hostName = "apollo";
networking.useDHCP = false;
networking.interfaces.ens3.useDHCP = true;
networking.interfaces.ens3.ipv4.addresses = [
{ address = "49.12.112.70"; prefixLength = 32; }
];
services.openssh.enable = true;
services.openssh.passwordAuthentication = false;
services.tailscale.enable = true;
system.copySystemConfiguration = true;
system.stateVersion = "20.09";
users.mutableUsers = true;
users.users.root.openssh.authorizedKeys.keys = auth-keys;
users.users.sol = {
isNormalUser = true;
extraGroups = [ "docker" "input" "wheel" ];
shell = pkgs.bash;
openssh.authorizedKeys.keys = auth-keys;
};
}

+ 11
- 0
nixops/hosts/apollo/system/boot.nix View File

@ -0,0 +1,11 @@
{ configs, pkgs, ... }:
{
boot.cleanTmpDir = true;
boot.kernelModules = [ "configfs" "fuse" ];
boot.kernelPackages = pkgs.linuxPackages_latest;
boot.loader.grub.enable = true;
boot.loader.grub.version = 2;
boot.loader.grub.device = "/dev/sda";
boot.tmpOnTmpfs = true;
}

+ 16
- 0
nixops/hosts/apollo/system/nixos.nix View File

@ -0,0 +1,16 @@
{ config, pkgs, lib, ... }:
{
nix.allowedUsers = lib.mkDefault [ "@users" ];
nix.autoOptimiseStore = true;
nix.buildCores = 4;
nix.gc = {
automatic = true;
dates = "daily";
options = "--delete-older-than 30d";
};
nix.maxJobs = 4;
nix.optimise.automatic = true;
nix.trustedUsers = [ "root" "sol" ];
nix.useSandbox = true;
}

+ 6
- 0
nixops/servers/configuration.nix View File

@ -0,0 +1,6 @@
{
network.description = "arcadia";
network.enableRollback = true;
apollo = import ../hosts/apollo;
}

+ 50
- 0
nixops/services/bitwarden.nix View File

@ -0,0 +1,50 @@
{ config, pkgs, lib, ... }:
let
unstable = import <nixos-unstable> { config = { allowUnfree = true; }; };
secrets = import ../configs/secrets.nix;
in {
services.bitwarden_rs = {
enable = true;
config = {
WEB_VAULT_FOLDER = "${pkgs.bitwarden_rs-vault}/share/bitwarden_rs/vault";
WEB_VAULT_ENABLED = true;
LOG_FILE = "/var/lib/bitwarden_rs/log";
WEBSOCKET_ENABLED= true;
WEBSOCKET_ADDRESS = "127.0.0.1";
WEBSOCKET_PORT = 3012;
ADMIN_TOKEN = secrets.bitwarden-admin-token;
DOMAIN = "https://pass.maych.in";
ROCKET_ADDRESS = "127.0.0.1";
ROCKET_PORT = 8812;
SIGNUPS_ALLOWED = false;
};
};
nixpkgs.config.packageOverrides = pkgs: {
bitwarden_rs = unstable.bitwarden_rs;
};
environment.systemPackages = with pkgs; [
unstable.bitwarden_rs-vault
];
services.nginx = {
virtualHosts."pass.maych.in" = {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "http://${config.services.bitwarden_rs.config.ROCKET_ADDRESS}:${toString config.services.bitwarden_rs.config.ROCKET_PORT}";
proxyWebsockets = true;
};
locations."/notifications/hub" = {
proxyPass = "http://${config.services.bitwarden_rs.config.WEBSOCKET_ADDRESS}:${toString config.services.bitwarden_rs.config.WEBSOCKET_PORT}";
proxyWebsockets = true;
};
locations."/notifications/hub/negotiate" = {
proxyPass = "http://${config.services.bitwarden_rs.config.ROCKET_ADDRESS}:${toString config.services.bitwarden_rs.config.ROCKET_PORT}";
proxyWebsockets = true;
};
};
};
}

+ 25
- 0
nixops/services/blog.nix View File

@ -0,0 +1,25 @@
{ config, pkgs, lib, ... }:
let
auth-keys = with import ../configs/ssh-keys.nix; [ blog ];
in {
users.users.blog = {
isNormalUser = true;
openssh.authorizedKeys.keys = auth-keys;
shell = pkgs.bash;
};
services.nginx = {
virtualHosts."maych.in" = {
enableACME = true;
forceSSL = true;
root = "/var/www/blog/maych.in";
};
virtualHosts."blog.maych.in" = {
enableACME = true;
forceSSL = true;
root = "/var/www/blog/blog.maych.in";
};
};
}

+ 56
- 0
nixops/services/drone.nix View File

@ -0,0 +1,56 @@
{ config, pkgs, lib, ... }:
let
secrets = import ../configs/secrets.nix;
in {
virtualisation.oci-containers = {
backend = "docker";
containers = {
drone = {
image = "drone/drone:latest";
environment = {
DRONE_AGENTS_ENABLED = "true";
DRONE_GIT_ALWAYS_AUTH = "false";
DRONE_GITEA_CLIENT_ID = secrets.drone-gitea-client-id;
DRONE_GITEA_CLIENT_SECRET = secrets.drone-gitea-client-secret;
DRONE_GITEA_SERVER = "https://git.maych.in";
DRONE_RPC_SECRET = secrets.drone-rpc-secret;
DRONE_SERVER_HOST = "ci.maych.in";
DRONE_SERVER_PROTO = "https";
DRONE_TLS_AUTOCERT = "false";
DRONE_USER_CREATE = "username:${secrets.drone-username},admin:true";
};
autoStart = true;
volumes = [
"/data/drone:/data"
];
ports = [ "127.0.0.1:8080:80" ];
};
drone-runner = {
image = "drone/agent:latest";
environment = {
DRONE_RPC_HOST = "ci.maych.in";
DRONE_RPC_PROTO = "https";
DRONE_RPC_SECRET = secrets.drone-rpc-secret;
DRONE_RUNNER_CAPACITY = "2";
DRONE_UI_USERNAME = secrets.drone-runner-user;
DRONE_UI_PASSWORD = secrets.drone-runner-password;
};
autoStart = true;
volumes = [
"/data/drone-agent:/data"
"/var/run/docker.sock:/var/run/docker.sock"
];
};
};
};
services.nginx = {
virtualHosts."ci.maych.in" = {
enableACME = true;
forceSSL = true;
locations."/".proxyPass = "http://localhost:8080/";
};
};
}

+ 72
- 0
nixops/services/firefly.nix View File

@ -0,0 +1,72 @@
{ config, pkgs, lib, ... }:
let
secrets = import ../configs/secrets.nix;
in {
virtualisation.oci-containers = {
backend = "docker";
containers = {
firefly = {
image = "jc5x/firefly-iii:latest";
environment = {
DB_CONNECTION = "pgsql";
DB_HOST = "fireflyiii-db";
DB_USERNAME = "firefly";
DB_PORT = "5432";
DB_PASSWORD = secrets.firefly-db-password;
DB_DATABASE = "firefly";
TZ = "Asia/Kolkata";
APP_URL = "https://firefly.maych.in";
APP_LOG_LEVEL = "debug";
MAIL_MAILER = "log";
TRUSTED_PROXIES = "**";
APP_KEY = secrets.firefly-app-key;
};
autoStart = true;
volumes = [
"/data/firefly-iii-export:/var/www/firefly-iii/storage/export"
"/data/firefly-iii-upload:/var/www/firefly-iii/storage/upload"
];
ports = [ "127.0.0.1:8081:8080" ];
extraOptions = [ "--network=firefly-network" ];
};
fireflyiii-db = {
image = "postgres:12-alpine";
environment = {
POSTGRES_USER = "firefly";
POSTGRES_PASSWORD = secrets.firefly-db-password;
};
autoStart = true;
volumes = [
"/data/firefly-iii-db:/var/lib/postgresql/data"
];
extraOptions = [ "--network=firefly-network" ];
};
};
};
services.nginx = {
virtualHosts."firefly.maych.in" = {
enableACME = true;
forceSSL = true;
locations."/".proxyPass = "http://localhost:8081/";
};
};
systemd.services.init-firefly-network = {
description = "Create a docker network bridge for firefly-iii";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig.Type = "oneshot";
script = ''
exists=$(${config.virtualisation.docker.package}/bin/docker network ls | grep "firefly-network" || true)
if [ -z "$exists" ]; then
${config.virtualisation.docker.package}/bin/docker network create firefly-network
else
echo "INFO: docker network firefly-network already exists"
fi
'';
};
}

+ 90
- 0
nixops/services/gitea.nix View File

@ -0,0 +1,90 @@
# NixOps configuration for the hosts running Gitea
{ config, pkgs, lib, ... }:
let
gitea-db-keyfile = "gitea-postgres"; # deployment.keys for db password
in {
services.gitea = {
enable = true;
appName = "Gitea";
cookieSecure = true;
disableRegistration = true;
user = "git";
database = {
name = "git";
user = "git";
type = "postgres";
passwordFile = "/run/keys/${gitea-db-keyfile}";
};
domain = "git.maych.in";
rootUrl = "https://git.maych.in/";
httpPort = 3000;
settings = let
docutils = pkgs.python37.withPackages (ps: with ps; [
docutils
pygments
]);
in {
mailer = {
ENABLED = true;
FROM = "git@maych.in";
};
security = {
DISABLE_GIT_HOOKS = true;
INSTALL_LOCK = true;
PASSWORD_COMPLEXITY = "off";
PASSWORD_CHECK_PWN = true;
};
service = {
REGISTER_EMAIL_CONFIRM = true;
};
"markup.restructuredtext" = {
ENABLED = true;
FILE_EXTENSIONS = ".rst";
RENDER_COMMAND = "${docutils}/bin/rst2html.py";
IS_INPUT_FILE = false;
};
};
};
services.postgresql = {
enable = true;
authentication = ''
local git all ident map=git-users
'';
identMap = ''
git-users git git
'';
ensureDatabases = [ "git" ];
ensureUsers = [
{
name = "git";
ensurePermissions = {
"DATABASE git" = "ALL PRIVILEGES";
"ALL TABLES IN SCHEMA public" = "ALL PRIVILEGES";
};
}
];
};
services.nginx = {
virtualHosts."git.maych.in" = {
enableACME = true;
forceSSL = true;
locations."/".proxyPass = "http://localhost:3000/";
};
};
users.users.git = {
isNormalUser = true;
home = config.services.gitea.stateDir;
extraGroups = [ "gitea" "keys" ];
shell = pkgs.bash;
};
systemd.services.gitea = {
after = [ "${gitea-db-keyfile}-key.service" ];
wants = [ "${gitea-db-keyfile}-key.service" ];
};
}

+ 27
- 0
nixops/services/nginx.nix View File

@ -0,0 +1,27 @@
# NixOps configuration for the hosts running Gitea
{ config, pkgs, lib, ... }:
{
services.nginx = {
enable = true;
package = pkgs.nginxMainline;
recommendedGzipSettings = true;
recommendedOptimisation = true;
recommendedProxySettings = true;
recommendedTlsSettings = true;
};
security.acme = {
acceptTerms = true;
email = "chinmaydpai@gmail.com";
};
networking.firewall = {
enable = true;
allowedTCPPorts = [
80
443
];
};
}

+ 29
- 0
nixops/services/ripe-atlas.nix View File

@ -0,0 +1,29 @@
{ config, pkgs, lib, ... }:
{
virtualisation.oci-containers = {
backend = "docker";
containers = {
ripe-atlas = {
image = "jamesits/ripe-atlas:latest";
environment = {
RXTXRPT = "yes";
};
autoStart = true;
volumes = [
"/data/ripe-atlas/etc:/var/atlas-probe/etc"
"/data/ripe-atlas/status:/var/atlas-probe/status"
];
extraOptions = [
"--cpus=1"
"--memory=64m"
"--memory-reservation=64m"
"--cap-add=SYS_ADMIN"
"--cap-add=NET_RAW"
"--cap-add=CHOWN"
"--mount=type=tmpfs,destination=/var/atlasdata,tmpfs-size=64M"
];
};
};
};
}

Loading…
Cancel
Save