diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fa69a9b --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +# ignore all unencrypted secrets files in this directory +./secrets/secrets.priv.yaml +./secrets/secrets.yaml.priv +./secrets/secrets.priv.yaml.gpg + diff --git a/machines/celebrian/README.md b/machines/celebrian/README.md new file mode 100644 index 0000000..dae31fa --- /dev/null +++ b/machines/celebrian/README.md @@ -0,0 +1,37 @@ +# things to setup on new headscale server +### setup nixos +1. get nixos running (preferably 22.11 or later) +2. get a way to paste the config file from this repo to /etc/nixos/configuration.nix (like over ssh) + +### domain provider +1. setup domain and domain and domain with wildcard to point to new server ip. +2. make sure any other domains that require this ingress points to it. +3. create a api key or similar to fit in a file like this. https://go-acme.github.io/lego/dns +4. create api kay file in /ver/lib/secrets/cert.secret, you can drop the \ and the last config line in the example from lego as this is not needed with nixos + + + + +### setup tailscale headscale +1. create a namespace in headscale. +2. add tailscale to headscale with ```sudo tailscale up --login-server https://vpn.example.domain ``` (could be localhost) +3. follow link in a browser, copy result command on this server, but replace USERNAME in --user USERNAME with namespace name (might be that headscale has updated and only uses namespaces as term now?) +4. add all other clients needed to tailscale again with the same process + +### done + +# add a new remote or nated service +1. add the machine running the service to the tailscale/headscale network like in install process +2. get the headscale name with ``` headscale nodes list ``` +3. go to configuration.nix with vim or another editor +4. add a virtual host to nginx for proxy, can copy one and change subdomain and proxy to machine + port, might remove basic auth if the service is intendend for everyone. + + +#Other solutions +might end in the situation where nixos is not an option and docker containers with diffrent things is my backup solution. +nothing is created yet but plan to use headscale with headscale-ui docker container in addition to something like nginxproxymanager,træfik or caddy. In this case use certbot or acme for certs i think. + +NGINX alternative: Caddy seems promising with tailscale integrated in the future. + +Tailscale/headscale alternative: plain wireguard, openvpn or + diff --git a/machines/celebrian/configuration.nix b/machines/celebrian/configuration.nix new file mode 100644 index 0000000..4c15234 --- /dev/null +++ b/machines/celebrian/configuration.nix @@ -0,0 +1,197 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ config, pkgs, lib, ... }: +{ + imports = + [ # Include the results of the hardware scan. + ./hardware-configuration.nix + ../profiles/base.nix + ../services/ssh.nix + ]; + + # Use the GRUB 2 boot loader. + boot.loader.grub.enable = true; + #boot.loader.grub.version = 2; #Depreciated + boot.loader.grub.efiSupport = true; + boot.loader.grub.device = "/dev/vda"; # or "nodev" for efi only # Define on which hard drive you want to install Grub. + + # Set your time zone. + time.timeZone = "Europe/Oslo"; + + + # The global useDHCP flag is deprecated, therefore explicitly set to false here. + # Per-interface useDHCP will be mandatory in the future, so this generated config + # replicates the default behaviour. + networking.useDHCP = false; + networking.interfaces.ens18.useDHCP = true; + networking.hostName = "addictedmaker"; # Define your hostname. + networking.domain = "addictedmaker.eu"; # Define your domain. + + boot.kernel.sysctl = { + "net.ipv4.conf.all.forwarding" = true; + "net.ipv6.conf.all.forwarding" = true; + }; + + # Select internationalisation properties. + i18n.defaultLocale = "en_US.UTF-8"; + console = { + font = "Lat2-Terminus16"; + keyMap = "no"; + + }; + + + # List packages installed in system profile. To search, run: + # $ nix search wget + environment.systemPackages = with pkgs; [ + git + wget + tailscale + config.services.headscale.package + kanidm + ]; + + users.users.gunalx = { # Define a user account. Don't forget to set a password with ‘passwd’. + isNormalUser = true; + extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user. + initialPassword = "pw123"; # this is changed imedeately. + }; + + + #add proxyserver to acme + users.users.kanidm.extraGroups = [ "acme" ]; + +#sequrity managment through kanidm + systemd.services.kanidm = let + certName = config.services.nginx.virtualHosts.${config.services.kanidm.serverSettings.domain}.useACMEHost; + in { + requires = [ "acme-finished-${certName}.target" ]; + serviceConfig.LoadCredential = let + certDir = config.security.acme.certs.${certName}.directory; + in [ + "fullchain.pem:${certDir}/fullchain.pem" + "key.pem:${certDir}/key.pem" + ]; + }; + + services.kanidm = { + enableServer = true; + #enablePam = true; + serverSettings = let + credsDir = "/run/credentials/kanidm.service"; + #credsDir = "/var/lib/acme/${config.networking.domain}"; #the files are here but not readable + in { + origin = "https://${config.services.kanidm.serverSettings.domain}"; + domain = "auth.${config.networking.domain}"; + tls_chain = "${credsDir}/fullchain.pem"; + tls_key = "${credsDir}/key.pem"; + bindaddress = "localhost:8300"; + }; + + clientSettings = { + # This should be at /etc/kanidm/config or ~/.config/kanidm, and configures the kanidm command line tool + uri = "${config.services.kanidm.serverSettings.bindaddress}"; + verify_ca = true; + verify_hostnames = true; + }; + }; + + #environment = { + # etc."kanidm/config".text = '' + # uri="https://auth.${config.networking.domain}" + # ''; + #}; + + +#vpn stuff + #need to run at fresh install to create namespace: headscale namespaces create + services.headscale = { + enable = true; + user = "headscale"; + address = "127.0.0.1"; + port = 8080; + settings = { + logtail.enabled = false; + metrics_listen_addr = "127.0.0.1:9090"; + server_url = "https://${"vpn."+config.networking.domain}"; + dns_config = { + base_domain = "${config.networking.domain}"; + magic_dns = true; + nameservers = [ + "1.1.1.1" + ]; + }; + + ##should really implement with fex github and kanidm + #oidc = { + # issuer = "{config.services.kanidm.serverSettings.origin}"; + # allowed_domains = Domains; + #}; + }; + }; + + #tailscale + services.tailscale.enable = true; + + # Enable the OpenSSH daemon. + services.openssh.enable = true; + services.openssh.settings.UseDns = true; + services.openssh.settings.PermitRootLogin = "prohibit-password"; + services.openssh.startWhenNeeded = true; + services.openssh.ports = [ 6969 ]; + services.endlessh.enable = true; #ssh honeypot + services.endlessh.port = 22; + services.endlessh.openFirewall = true; + services.sshguard.enable = true; #protection against brute force attacks like fail2ban + + users.users."root".openssh.authorizedKeys.keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHTExYoT3+flrd2wPYiT7sFFDmAUqi2YAz0ldQg7WMop" + ]; +users.users."gunalx".openssh.authorizedKeys.keys = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHTExYoT3+flrd2wPYiT7sFFDmAUqi2YAz0ldQg7WMop" + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEj+Y0RUrSaF8gUW8m2BY6i8e7/0bUWhu8u8KW+AoHDh gunalx@nixos" + ]; + + #fail2ban + services.fail2ban = { + enable = true; + maxretry = 5; + ignoreIP = [ + "127.0.0.0/8" + "10.0.0.0/8" + "100.64.0.0/8" + "172.16.0.0/12" + "192.168.0.0/16" + "8.8.8.8" + ]; + }; + + #firewall options + networking.firewall = { + enable = true; + checkReversePath = "loose"; + trustedInterfaces = [ "tailscale0" ]; + allowedUDPPorts = [ + 8096 + 80 + 443 + #config.services.openssh.ports + config.services.tailscale.port + config.services.headscale.port + ]; + allowedTCPPorts = config.networking.firewall.allowedUDPPorts; + }; + + # not needed in this config but should sty in default configuration.nix + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + #system.stateVersion = "20.09"; # Did you read the comment? + +} diff --git a/machines/feanor/README.md b/machines/feanor/README.md new file mode 100644 index 0000000..61d41e1 --- /dev/null +++ b/machines/feanor/README.md @@ -0,0 +1,5 @@ +gitserver with gitea +webserver with homepage + +webserver implementation is in works +thinking of doing something like diff --git a/machines/feanor/configuration.nix b/machines/feanor/configuration.nix new file mode 100644 index 0000000..e69de29 diff --git a/machines/galadriel/README.md b/machines/galadriel/README.md new file mode 100644 index 0000000..605a57e --- /dev/null +++ b/machines/galadriel/README.md @@ -0,0 +1,9 @@ +services +jellyfin + +services in need of configuration +transmission +sonarr + +to be implemented +calibre diff --git a/machines/galadriel/configuration.nix b/machines/galadriel/configuration.nix new file mode 100644 index 0000000..b941a4a --- /dev/null +++ b/machines/galadriel/configuration.nix @@ -0,0 +1,181 @@ +# Edit this configuration file to define what should be installed on +# your system. Help is available in the configuration.nix(5) man page +# and in the NixOS manual (accessible by running ‘nixos-help’). + +{ config, pkgs, ... }: + +{ + imports = + [ # Include the results of the hardware scan. + ./hardware-configuration.nix + ./vim.nix + ]; + + # Bootloader. + boot.loader.grub.enable = true; + boot.loader.grub.device = "/dev/sda"; + boot.loader.grub.useOSProber = true; + + networking.hostName = "galadriel"; # Define your hostname. + # networking.wireless.enable = true; # Enables wireless support via wpa_supplicant. + + # Configure network proxy if necessary + # networking.proxy.default = "http://user:password@proxy:port/"; + # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; + + # Enable networking + networking.networkmanager.enable = true; + + # Set your time zone. + time.timeZone = "Europe/Oslo"; + + # Select internationalisation properties. + i18n.defaultLocale = "en_US.UTF-8"; + + # Configure keymap in X11 + services.xserver = { + layout = "no"; + xkbVariant = ""; + }; + + # Configure console keymap + console.keyMap = "no"; + + # Define a user account. Don't forget to set a password with ‘passwd’. + users.users.gunalx = { + isNormalUser = true; + description = "gunalx"; + extraGroups = [ "networkmanager" "wheel" ]; + packages = with pkgs; []; + }; + + # Allow unfree packages + nixpkgs.config.allowUnfree = true; + + # List packages installed in system profile. To search, run: + # $ nix search wget + environment.systemPackages = with pkgs; [ + vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default. + wget + git + rsync + nfs-utils + cifs-utils + tailscale + jellyfin + jellyfin-web + jellyfin-mpv-shim + jftui + sonixd + sonarr + bazarr + unpackerr + freshrss + ]; + + # Some programs need SUID wrappers, can be configured further or are + # started in user sessions. + # programs.mtr.enable = true; + # programs.gnupg.agent = { + # enable = true; + # enableSSHSupport = true; + # }; + + # List services that you want to enable: + +##productivity + services.tandoor-recipes.enable = true; + +##media + services.jellyfin.enable = true; + services.komga.enable = true; + + services.polaris.enable = true; + services.navidrome.enable = true; + + services.podgrab.enable = true; + services.podgrab.port = 4242; + + + services.calibre-web.enable = true; + #services.calibre-server.enable = true; + + services.freshrss.enable = true; #rss aggregator + services.freshrss.baseUrl = "http://127.0.0.1"; + services.freshrss.passwordFile = "/run/secrets/freshrss"; + +##downloading + #autodownload + services.sonarr.enable = true; + services.radarr.enable = true; + services.lidarr.enable = true; + services.bazarr.enable = true; + +#indexing + services.prowlarr.enable = true; + services.jackett.enable = true; + + #torrent managment + services.transmission.enable = true; + +##networking + # Enable the OpenSSH daemon. + services.openssh.enable = true; + + #tailscale + services.tailscale.enable = true; + + # Open ports in the firewall. + # networking.firewall.allowedTCPPorts = [ ... ]; + # networking.firewall.allowedUDPPorts = [ ... ]; + # Or disable the firewall altogether. + networking.firewall.enable = false; + +##storage + + + #autofs + #services.autofs.enable = true; + + #smb share + + #nfs share + #services.nfs.server = { + # enable = true; + # # fixed rpc.statd port; for firewall + # lockdPort = 4001; + # mountdPort = 4002; + # statdPort = 4000; + # extraNfsdConfig = ''''; + #}; + + + #zfs stuff if needed + + + #mounts + fileSystems."/mnt/nas" = { + device = "192.168.1.137:/mnt/Main/Home"; + fsType = "nfs"; + + options = [ + #"nfsvers=4.2" + "x-systemd.automount" "noauto" + "x-systemd.idle-timeout=600" + ]; + }; + + + + + +#default scary stuff + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "22.11"; # Did you read the comment? + +} diff --git a/machines/galadriel/vim.nix b/machines/galadriel/vim.nix new file mode 100644 index 0000000..a5a0547 --- /dev/null +++ b/machines/galadriel/vim.nix @@ -0,0 +1,25 @@ +{ pkgs, ... }: +{ + programs.neovim = { + enable = true; + viAlias = true; + vimAlias = true; + defaultEditor = true; + + configure = { + customRC = '' + " your custom vimrc + set nocompatible + set backspace=indent,eol,start + " Turn on syntax highlighting by default + syntax on + set autoindent + " ... + ''; + packages.myplugins = with pkgs.vimPlugins; { + start = [ vim-nix vim-lastplace vim-yaml ]; + opt = []; + }; + }; + }; +} diff --git a/packages/vim.nix b/packages/vim.nix new file mode 100644 index 0000000..1696048 --- /dev/null +++ b/packages/vim.nix @@ -0,0 +1,24 @@ +{ pkgs, ... }: +{ + programs.neovim = { + enable = true; + viAlias = true; + vimAlias = true; + defaultEditor = true; + + configure = { + customRC = '' + " your custom vimrc + set nocompatible + set backspace=indent,eol,start + " Turn on syntax highlighting by default + syntax on + " ... + ''; + packages.myplugins = with pkgs.vimPlugins; { + start = [ vim-nix vim-lastplace vim-yaml ]; + opt = []; + }; + }; + }; +} diff --git a/profiles/base.nix b/profiles/base.nix new file mode 100644 index 0000000..d6c203d --- /dev/null +++ b/profiles/base.nix @@ -0,0 +1,13 @@ +{ config, pkgs, lib, ... }: +{ +imports = + [ + ../packages/vim.nix + ./sops.nix + ]; + + #nix stuff + nix.gc.automatic = true; + system.autoUpgrade.enable = true; + +} \ No newline at end of file diff --git a/profiles/sops.nix b/profiles/sops.nix new file mode 100644 index 0000000..70eedee --- /dev/null +++ b/profiles/sops.nix @@ -0,0 +1,27 @@ +{ config, pkgs, ... }: +{ + environment.systemPackages = [ + pkgs.ssh-to-age + pkgs.sops + ]; + + imports = [ "${builtins.fetchTarball "https://github.com/Mic92/sops-nix/archive/master.tar.gz"}/modules/sops" ]; + + # This will add secrets.yml to the nix store + # You can avoid this by adding a string to the full path instead, i.e. + # sops.defaultSopsFile = "/root/.sops/secrets/example.yaml"; + sops.defaultSopsFile = ./secrets.yaml; + # This will automatically import SSH keys as age keys + sops.age.sshKeyPaths = [ "/etc/ssh/nixos" "/$HOME/.ssh/nixos" "/home/gunalx/.ssh/nixos" ]; + # This is using an age key that is expected to already be in the filesystem + # sops.age.keyFile = "/var/lib/sops-nix/key.txt"; + # This will generate a new key if the key specified above does not exist + sops.age.generateKey = true + + # This is the actual specification of the secrets. + #sops.secrets."myservice/my_subdir/my_secret" = {}; + sops.secrets."acme/creds/domeneshop" = { + + }; + +} diff --git a/secrets/nixos.pub b/secrets/nixos.pub new file mode 100644 index 0000000..d9c834f --- /dev/null +++ b/secrets/nixos.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEj+Y0RUrSaF8gUW8m2BY6i8e7/0bUWhu8u8KW+AoHDh gunalx@nixos \ No newline at end of file diff --git a/secrets/secrets.yaml b/secrets/secrets.yaml new file mode 100644 index 0000000..8dbccba --- /dev/null +++ b/secrets/secrets.yaml @@ -0,0 +1,24 @@ +#ENC[AES256_GCM,data:D56rhkcdzYvGA391Yd/xtA==,iv:7a7XGF/5Am07S6GIH97dae8bZ14kBN/hST1DK2QkVbc=,tag:cAFYNF6AScu2SCECMiNpaw==,type:comment] +#ENC[AES256_GCM,data:whBqc+AeZpCDo/caKJQm3Wan3RiAvQwQ0v4fgmdZhMTu+5QeTTqb1L1M6ZUnNnQS1tc9wjaWfXby/2T0zLDM+Yl3yuHSfK1rkBbC4GwL83tSM4lbDE7+spSKxb2VrOZqozKpL6zQnWJB0COJfC5KqlHJCiM=,iv:M1KPhEQS/l4OFwAClqr7L2Jf73/tkpBBmXEPjGI7faU=,tag:A5x4nCDbnOLplGh7xqdN2Q==,type:comment] +acme: + certs: ENC[AES256_GCM,data:glU5Kl4wiChxuQJq2ppCP4sJlutJkK1RgV0FloMNe/W8rV/mHcg8FcffotNYVZw87mqWz3N4jMgMVwnmXU0uObhV+W6L0mMb9U7akhXIuJQfiwaTeHZV48DPzDBzIDHUrsPZfxm6vfBlJltk9dH/43lytyMJqSeV3nWW4rA=,iv:Nz2pDdPdVbZK6BuYJrPcZ/LnnruvuMlhMJeowUPADj0=,tag:YNtlgq04iJxnZL76ESsQaQ==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: + - recipient: age14cpm59h7hx8gr54hrn4uxu4xnrp9wy3f2kdxvy6xwuyxsfg8g9zs8z5e77 + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxczVMVEROU0k1TFAwcDhZ + YlVwOVpSYVhjT0oveGlLMUhJak40Q3E0UzFRCjFlV1h4ektaSTdvdnBLTjdYQ0pz + VVFWbFFYODVBNzdCRkw4Q3pKYzZ6RjAKLS0tIGxtbWR6MnFVZUNyWHl3T0lBSXQz + Vmg2SkZBdjFYM1MzdVhmRVVNYjg3MlkKPbXkDdChq+GqqZuwQ2rj5LIP1gA44Qxn + gI66sDKkBwkAx7EkvUejGXK4pqPPvRwDUZFoSowIOSGaxF7CKdayBA== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2023-09-24T01:30:23Z" + mac: ENC[AES256_GCM,data:4ji9jVU4oILYTr3Hfd3Ic1XsxFrOnKTyTY88p9WCO8SaWDqzu2e/W3O8tiMgeZChTLLi0pK6t2hUgLI9XAQFQswMi56Ues1XdR+a8SsQmsMb0oGDzd6/Nhe39G0Q9raAy0XC+j9lBapOgKPKLGlDXRlllA050nFkTWEhKCQJmg8=,iv:FPYTaoDZjsbu6Oc0qu35jHq/AUhbfbnirutmcKDuUG8=,tag:JeQB+Fs2WOdlV7XoBFi3ag==,type:str] + pgp: [] + unencrypted_suffix: _unencrypted + version: 3.8.0 diff --git a/services/nginx.nix b/services/nginx.nix new file mode 100644 index 0000000..86b379e --- /dev/null +++ b/services/nginx.nix @@ -0,0 +1,76 @@ +{ config, pkgs, lib, ... }: +let + basicAuthUser = "guest"; + basicAuthPass = "12345678"; +in +{ + + #acme and certs helpful blog https://carjorvaz.com/posts/ + security.acme = { + acceptTerms = true; + defaults.email = "adrian+acme@lauterer.it"; + + certs."${config.networking.domain}" = { + domain = "${config.networking.domain}"; + extraDomainNames = [ "*.${config.networking.domain}" "lauterer.it" "*.lauterer.it" "*.256.no" "*.256.no"]; + dnsProvider = "domeneshop"; # from here according to privider https://go-acme.github.io/lego/dns/ + dnsPropagationCheck = true; + credentialsFile = config.sops.secrets."acme/creds/domeneshop".path; #need to manually create this file according to dnsprovider secrets, and format of key according to lego in privider and add to secrets.yaml + }; + }; + + #add proxyserver to acme + users.users.nginx.extraGroups = [ "acme" ]; + users.users.root.extraGroups = [ "acme" ]; + + #TODO add oauth2 proxy to auth + # services.oauth2_proxy = { + # enable = true; + # } + + + #proxy stuff + services.nginx = { + enable = true; + statusPage = true; + enableReload = true; + recommendedTlsSettings = true; + recommendedProxySettings = true; + recommendedGzipSettings = true; + recommendedOptimisation = true; + + virtualHosts.${"vpn."+config.networking.domain} = { + forceSSL = true; + useACMEHost = "${config.networking.domain}"; + locations."/" = { + proxyWebsockets = true; + proxyPass = "http://localhost:${toString config.services.headscale.port}"; + }; + }; + + virtualHosts.${config.services.kanidm.serverSettings.domain} = { # (auth.) + forceSSL = true; + useACMEHost = "${config.networking.domain}"; + locations."/" = { + proxyWebsockets = true; + proxyPass = "${"https://"+config.services.kanidm.serverSettings.bindaddress}"; + + }; + }; + + virtualHosts.${"jellyfin."+config.networking.domain} = { + forceSSL = true; + #enableACME = true; + useACMEHost = "${config.networking.domain}"; + locations."/" = { + proxyPass = "http://jellyfin.galadriel"; + proxyWebsockets = true; + basicAuth = { + guest = basicAuthPass; + }; + }; + }; + }; + + +} diff --git a/services/ssh.nix b/services/ssh.nix new file mode 100644 index 0000000..7f8e30b --- /dev/null +++ b/services/ssh.nix @@ -0,0 +1,33 @@ +{ config, pkgs, lib, ... }: +{ + environment.systemPackages = [ + pkgs.openssh + pkgs.endlessh + pkgs.sshguard + ]; + + services.openssh = { + enable = true; + settings.UseDns = true; + settings.PermitRootLogin = "prohibit-password"; + startWhenNeeded = true; + UseDns = true; + ports = [ 25264 ]; + openFirewall = true; + Ciphers = [ + "chacha20-poly1305@openssh.com" + "aes256-gcm@openssh.com" + "aes128-gcm@openssh.com" + "aes256-ctr" + # remove some weaker ciphers + ] + } + endlessh = { + enable = true; + port = 22; + openFirewall = true; + }; + sshguard.enable = true; #protection against brute force attacks like fail2ban + + +} \ No newline at end of file