diff --git a/configuration.nix b/configuration.nix deleted file mode 100644 index de14efb9..00000000 --- a/configuration.nix +++ /dev/null @@ -1,147 +0,0 @@ -# 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 - ./common.nix - ./box.nix - ]; - - # Use the GRUB 2 boot loader. - boot.loader.efi.canTouchEfiVariables = true; - boot.loader.efi.efiSysMountPoint = "/boot/efi"; - boot.loader.grub = { - enable = true; - device = "nodev"; - version = 2; - efiSupport = true; - enableCryptodisk = true; - }; - - boot.initrd.secrets = { - "/keyfile0.bin" = /etc/secrets/initrd/keyfile0.bin; - "/keyfile1.bin" = /etc/secrets/initrd/keyfile1.bin; - }; - - boot.initrd.luks.devices = { - "root" = { - #name = "root"; - device = "/dev/disk/by-uuid/f37f3222-47d7-42d8-b400-363320a31853"; # UUID for /dev/nvme01np2 - preLVM = true; - allowDiscards = true; - keyFile = "/keyfile0.bin"; - }; - }; - - # Data mount - fileSystems."/data" = { - device = "/dev/disk/by-uuid/3276a297-9ee4-4998-b262-1ed100366c06"; # UUID for /dev/mapper/crypted-data - encrypted = { - enable = true; - label = "crypted-data"; - blkDev = "/dev/disk/by-uuid/8a317bf4-fe13-4334-a6df-5fe5a5048b5e"; # UUID for /dev/sda1 - keyFile = "/keyfile1.bin"; - }; - }; - - # boot.loader.grub.efiInstallAsRemovable = true; - # boot.loader.efi.efiSysMountPoint = "/boot/efi"; - # Define on which hard drive you want to install Grub. - # boot.loader.grub.device = "/dev/sda"; # or "nodev" for efi only - - networking.hostName = "box"; # Define your hostname. - # networking.wireless.enable = true; # Enables wireless support via wpa_supplicant. - - # 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.enp0s31f6.useDHCP = true; - networking.interfaces.enp3s0.useDHCP = true; - networking.interfaces.wlp4s0.useDHCP = true; - - # OpenVPN - services.openvpn.servers = { - officeVPN = - { config = '' - config /home/anish/usr/work/ThreatDefence/vpn/anishcarbon19.ovpn ''; - autoStart = false; - updateResolvConf = true; - }; - }; - # Configure network proxy if necessary - # networking.proxy.default = "http://user:password@proxy:port/"; - # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; - - # Select internationalisation properties. - # i18n = { - # consoleFont = "Lat2-Terminus16"; - # consoleKeyMap = "us"; - # defaultLocale = "en_US.UTF-8"; - # }; - - # Set your time zone. - # time.timeZone = "Europe/Amsterdam"; - - # List packages installed in system profile. To search, run: - # $ nix search wget - # environment.systemPackages = with pkgs; [ - # wget vim - # ]; - - # 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: - - # Enable the OpenSSH daemon. - services.openssh.enable = true; - services.openssh.permitRootLogin = "yes"; - - # Open ports in the firewall. - # networking.firewall.allowedTCPPorts = [ ... ]; - # networking.firewall.allowedUDPPorts = [ ... ]; - # Or disable the firewall altogether. - # networking.firewall.enable = false; - - # Enable CUPS to print documents. - # services.printing.enable = true; - - # Enable sound. - sound.enable = true; - # hardware.pulseaudio.enable = true; - - # Enable the X11 windowing system. - # services.xserver.enable = true; - # services.xserver.layout = "us"; - # services.xserver.xkbOptions = "eurosign:e"; - - # Enable touchpad support. - # services.xserver.libinput.enable = true; - - # Enable the KDE Desktop Environment. - # services.xserver.displayManager.sddm.enable = true; - # services.xserver.desktopManager.plasma5.enable = true; - - # Define a user account. Don't forget to set a password with ‘passwd’. - users.users.anish = { - isNormalUser = true; - extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user. - hashedPassword = "MO0Pbd2O4eIlA"; - }; - - # This value determines the NixOS release with which your system is to be - # compatible, in order to avoid breaking some software such as database - # servers. You should change this only after NixOS release notes say you - # should. - system.stateVersion = "19.09"; # Did you read the comment? - -} - diff --git a/hardware-configuration.nix b/hardware-configuration.nix deleted file mode 100644 index a8db8d4e..00000000 --- a/hardware-configuration.nix +++ /dev/null @@ -1,32 +0,0 @@ -# Do not modify this file! It was generated by ‘nixos-generate-config’ -# and may be overwritten by future invocations. Please make changes -# to /etc/nixos/configuration.nix instead. -{ config, lib, pkgs, ... }: - -{ - imports = - [ - ]; - - boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "usb_storage" "usbhid" "sd_mod" ]; - boot.initrd.kernelModules = [ "dm-snapshot" ]; - boot.kernelModules = [ "kvm-intel" ]; - boot.extraModulePackages = [ ]; - - fileSystems."/" = - { device = "/dev/disk/by-uuid/ade0752d-84d3-4e39-865b-9027ba2d5c67"; - fsType = "ext4"; - }; - - fileSystems."/boot/efi" = - { device = "/dev/disk/by-uuid/1715-278E"; - fsType = "vfat"; - }; - - swapDevices = - [ { device = "/dev/disk/by-uuid/b790abb4-ba5f-4476-8f09-b0fc575414aa"; } - ]; - - nix.maxJobs = lib.mkDefault 4; - powerManagement.cpuFreqGovernor = lib.mkDefault "powersave"; -} diff --git a/machines/bowl.nix b/machines/bowl.nix new file mode 100644 index 00000000..70deb4fd --- /dev/null +++ b/machines/bowl.nix @@ -0,0 +1,74 @@ +{ config, pkgs, ... }: +{ +imports = + [ # Include the results of the hardware scan. + ./hardware-configuration.nix + ./taskd.nix + ./nextcloud.nix + ./networking.nix +# ./wireguard.nix +# ./shiori.nix + ./shaarli.nix +# ./shaarli-tokudan.nix +# ./mod-wallabag.nix +# ./pkg-wallabag.nix + ./navidrome.nix + ./pkg-navidrome.nix +# ./wallabag.nix + ./headphones.nix + ./dns.nix + ./backup.nix + ./monitoring.nix + ]; + + boot.loader.grub.devices = [ "/dev/sda" ]; + boot.loader.grub.enable = true; + boot.loader.grub.version = 2; + boot.loader.grub.enableCryptodisk = true; + boot.loader.supportsInitrdSecrets = true; + + boot.initrd.kernelModules = [ "dm-snapshot" ]; + boot.initrd.availableKernelModules = ["virtio-pci"]; + boot.initrd.network = { + enable = true; + ssh = { + enable = true; + port = 2222; + authorizedKeys = ["ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDKN8/SH55DBiwVoSnTU8k2Pen+wmovL9QaMyehxGEsJJv/8fzwsswGalD4C/4O51LOvdu4UKkZW5hG02uVSK+58p3UV3pOPyoqsu/aDeIsWsqmTeTzUrBIWOlNzcDKnohLz2oGC5YO+wyTJ9Iteq6aGJDjErsW7sG3h5lXCs551EmJNNGhtBQaaoytMNnWqSdlVjDNCijurH7WUpp40U/RjEp532l4rX6eIIj3jBKEFbhZkFSSjqbj4xM4SyFt+Jmigb1RMjsQjmpfY1vDtM84RcYfpTUte/T5w2dkD5H6kccmWnwKSJpm9wXfx4E7lR9APdUGnau2U1+XxiD3ytGl anish@box +"]; + hostKeys = [ "/host_ecdsa_key" ]; + }; + }; + + boot.initrd.luks.devices = { + "enc-pv" = { + name = "enc-pv"; + preLVM = true; + device = "/dev/disk/by-uuid/425cc402-9221-474f-aaf1-10ac7cd4c93c"; + allowDiscards = true; + }; + }; + + boot.initrd.secrets = { + "/host_ecdsa_key" = "/host_ecdsa_key"; + }; + + + boot.cleanTmpDir = true; + boot.kernelModules = [ "dm-snapshot" ]; + + users.users.anish = { + isNormalUser = true; + extraGroups = [ "wheel" ]; + hashedPassword = "MO0Pbd2O4eIlA"; + openssh.authorizedKeys.keys = [ "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDKN8/SH55DBiwVoSnTU8k2Pen+wmovL9QaMyehxGEsJJv/8fzwsswGalD4C/4O51LOvdu4UKkZW5hG02uVSK+58p3UV3pOPyoqsu/aDeIsWsqmTeTzUrBIWOlNzcDKnohLz2oGC5YO+wyTJ9Iteq6aGJDjErsW7sG3h5lXCs551EmJNNGhtBQaaoytMNnWqSdlVjDNCijurH7WUpp40U/RjEp532l4rX6eIIj3jBKEFbhZkFSSjqbj4xM4SyFt+Jmigb1RMjsQjmpfY1vDtM84RcYfpTUte/T5w2dkD5H6kccmWnwKSJpm9wXfx4E7lR9APdUGnau2U1+XxiD3ytGl anish@box ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDM8kTdMGGmr6mv/zv+K9qVjhzqwivyyN5IV04R7/kcWKw1c6ZEzzqqmsnJ/hci6IIxZ/VEUzMhYz0iBCL0wJHHMxYoNCgISWePtDlVJdyrzm9OWjJNcRStZBW3XcY9dELJsCVcQ4LAVYE4vA+MdmbwM2FZgJhAH6qUzujpfNrj/YIVG7MTN6tbUd63uZF57F43c8WUjgRJx2o7Wl9bSe6v3PZ4fAgEO+wQPso+W+pEXLZ3hBNrHdybwdoGvG9tHlBDbLid11BxtpzmwR9CydDfpbyOXB2+tJkkNXhsHB22mN/2+vGWYhDKYPTFqbDW7McDfQChySyYDdZWmg5WHIGz anish@curve" ]; + }; + + users.users.root.initialHashedPassword = ""; + services.openssh.permitRootLogin = "prohibit-password"; + networking.hostName = "bowl"; + services.openssh.enable = true; + services.logind.lidSwitch = "ignore"; + system.stateVersion = "20.09"; + time.timeZone = "Australia/Brisbane"; +} diff --git a/box.nix b/machines/box.nix similarity index 100% rename from box.nix rename to machines/box.nix diff --git a/modules/backup.nix b/modules/backup.nix new file mode 100644 index 00000000..8fa6f01c --- /dev/null +++ b/modules/backup.nix @@ -0,0 +1,34 @@ +{ + # Assumes the remote borg backup server has already been initialized + # borg init --encryption-key=repokey-blake2 -rsh 'ssh -i /run/keys/id_ed25519_borgbase' 20779@hk-s020.rsync.net: + services.borgbackup.jobs = { + backupTaskwarriorRsync = { + paths = [ "/var/lib/taskserver" ]; + doInit = true; + repo = "20779@hk-s020.rsync.net:taskwarrior" ; + encryption = { + mode = "repokey-blake2"; + passCommand = "cat /run/keys/rsync"; + }; + environment = { BORG_RSH = "ssh -i /run/keys/id_ed25519_borgbase"; }; + compression = "auto,lzma"; + startAt = "weekly"; + extraArgs = "--remote-path=borg1"; + }; + }; + services.borgbackup.jobs = { + backupShaarliRsync = { + paths = [ "/var/www/shaarli-config/data/datastore.php" "/var/www/shaarli-config/config" "/var/www/shaarli-config/.json.config" ]; + doInit = true; + repo = "20779@hk-s020.rsync.net:shaarli" ; + encryption = { + mode = "repokey-blake2"; + passCommand = "cat /run/keys/rsync"; + }; + environment = { BORG_RSH = "ssh -i /run/keys/id_ed25519_borgbase"; }; + compression = "auto,lzma"; + startAt = "weekly"; + extraArgs = "--remote-path=borg1"; + }; + }; +} diff --git a/common.nix b/modules/common.nix similarity index 100% rename from common.nix rename to modules/common.nix diff --git a/modules/dns.nix b/modules/dns.nix new file mode 100644 index 00000000..c08693c8 --- /dev/null +++ b/modules/dns.nix @@ -0,0 +1,11 @@ +{ config, pkgs, lib, ... }: +{ + services.dnsmasq.enable = true; + services.dnsmasq.extraConfig = '' + address=/.mossnet.lan/192.168.1.6 + dhcp-range=192.168.1.1,proxy + ''; + services.dnsmasq.servers = [ "45.90.30.49" "45.90.28.49" "1.1.1.1" "8.8.8.8" ]; + networking.firewall.allowedTCPPorts = [ 53 ]; + networking.firewall.allowedUDPPorts = [ 53 ]; +} diff --git a/modules/headphones.nix b/modules/headphones.nix new file mode 100644 index 00000000..a76c6d5d --- /dev/null +++ b/modules/headphones.nix @@ -0,0 +1,12 @@ +{config, lib, pkgs, ... }: +{ + services.headphones = { + enable = true; + host = "192.168.1.6"; + port = 8181; + user = "headphones"; + group = "headphones"; + dataDir = "/data/downloaded"; + }; + networking.firewall.allowedTCPPorts = [ 8181 ]; +} diff --git a/modules/mod-shaarli.nix b/modules/mod-shaarli.nix new file mode 100644 index 00000000..b3e0b52c --- /dev/null +++ b/modules/mod-shaarli.nix @@ -0,0 +1,80 @@ +{ config, lib, pkgs, ... }: + +let + phppoolName = "shaarli"; + dataDir = "/var/lib/shaarli"; + vhost = "192.168.1.6:1233"; + + shaarli = pkgs.callPackage ./pkg-shaarli.nix { + inherit dataDir; + }; +in +{ + services.nginx.virtualHosts."${vhost}" = { + forceSSL = false; + enableACME = false; + root = "${shaarli}"; + listen = [ { addr = "192.168.1.6"; port = 1233; } ]; + # extraConfig = '' + # index index.php; + # ''; + locations."/" = { + index = "index.php"; + extraConfig = '' + try_files $uri $uri/ index.php; + ''; + }; + locations."~ (index)\.php$" = { + extraConfig = '' + fastcgi_split_path_info ^(.+\.php)(/.*)$; + if (!-f $document_root$fastcgi_script_name) { + return 404; + } + + include ${pkgs.nginx}/conf/fastcgi.conf; + fastcgi_pass unix:${config.services.phpfpm.pools."${phppoolName}".socket}; + fastcgi_index index.php; + ''; + }; + locations."~ \.php$" = { + extraConfig = '' + deny all; + ''; + }; + }; + services.phpfpm.pools."${phppoolName}" = { + user = "nginx"; + group = "nginx"; + settings = { + "listen.owner" = "nginx"; + "listen.group" = "nginx"; + "user" = "nginx"; + "pm" = "dynamic"; + "pm.max_children" = "75"; + "pm.min_spare_servers" = "5"; + "pm.max_spare_servers" = "20"; + "pm.max_requests" = "10"; + "catch_workers_output" = "1"; + }; + }; + users.extraUsers.shaarli = { group = "shaarli"; }; + users.extraGroups.shaarli = { }; + systemd.services.shaarli-install = { + serviceConfig.Type = "oneshot"; + wantedBy = [ "multi-user.target" ]; + script = '' + if [ ! -d "${dataDir}" ]; then + mkdir -p ${dataDir}/{cache,data,pagecache,tmp} + cp -R ${shaarli}/data.orig/.htaccess ${dataDir}/cache/ + cp -R ${shaarli}/data.orig/.htaccess ${dataDir}/data/ + cp -R ${shaarli}/data.orig/.htaccess ${dataDir}/pagecache/ + cp -R ${shaarli}/data.orig/.htaccess ${dataDir}/tmp/ + fi + chown -Rc nginx:nginx ${dataDir} + find ${dataDir} -type d ! -perm 0700 -exec chmod 0700 {} \; -exec chmod g-s {} \; + find ${dataDir} -type f ! -perm 0600 -exec chmod 0600 {} \; + ''; + }; + + networking.firewall.allowedTCPPorts = [ 1233 ]; +} diff --git a/modules/mod-wallabag.nix b/modules/mod-wallabag.nix new file mode 100644 index 00000000..fc6f7ff1 --- /dev/null +++ b/modules/mod-wallabag.nix @@ -0,0 +1,263 @@ +{ config, lib, pkgs, ... }: + +with lib; +let + cfg = config.services.wallabag; + + poolName = "wallabag"; + + phpfpmSocketName = "/var/run/phpfpm/${poolName}.sock"; + + configFile = pkgs.writeTextFile { + name = "wallabag-config"; + text = cfg.conf; + destination = "/config/parameters.yml"; + }; + + appDir = pkgs.buildEnv { + name = "wallabag-app-dir"; + ignoreCollisions = true; + checkCollisionContents = false; + paths = [ configFile "${cfg.package}/app" ]; + }; + +in { + options = { + services.wallabag = { + enable = mkEnableOption "wallabag"; + + user = mkOption { + type = types.str; + default = "nginx"; + description = '' + User account under which both the update daemon and the web-application run. + ''; + }; + + dataDir = mkOption { + type = types.path; + default = "/var/www/wallabag"; + description = '' + Data directory. + ''; + }; + + package = mkOption { + type = types.package; + default = pkgs.wallabag; + description = '' + Wallabag package to use. + ''; + }; + + hostName = mkOption { + type = types.str; + description = '' + Name of the nginx virtualhost to use and setup. + ''; + }; + + poolConfig = mkOption { + type = types.lines; + default = '' + pm = dynamic + pm.max_children = 75 + pm.start_servers = 1 + pm.min_spare_servers = 1 + pm.max_spare_servers = 20 + pm.max_requests = 500 + catch_workers_output = 1 + ''; + description = '' + Options for wallabag's PHP pool. See the documentation on php-fpm.conf for details on configuration directives. + ''; + }; + + conf = mkOption { + type = types.str; + default = '' +parameters: + database_driver: pdo_pgsql + database_driver_class: Wallabag\CoreBundle\Doctrine\DBAL\Driver\CustomPostgreSQLDriver + database_host: 127.0.0.1 + database_port: ~ + database_name: wallabag + database_user: wallabag + database_password: ~ + # For SQLite, database_path should be "%kernel.project_dir%/data/db/wallabag.sqlite" + database_path: null + database_table_prefix: wallabag_ + database_socket: null + # with PostgreSQL and SQLite, you must set "utf8" + database_charset: utf8 + + domain_name: http://192.168.1.6:8080 + + mailer_transport: smtp + mailer_user: ~ + mailer_password: ~ + mailer_host: 127.0.0.1 + mailer_port: false + mailer_encryption: ~ + mailer_auth_mode: ~ + locale: en + # A secret key that's used to generate certain security-related tokens + secret: sateofg893964crfSTNFG"*(&@$091 + twofactor_auth: true + twofactor_sender: no-reply@wallabag.org + fosuser_registration: true + fosuser_confirmation: true + fos_oauth_server_access_token_lifetime: 3600 + fos_oauth_server_refresh_token_lifetime: 1209600 + from_email: no-reply@wallabag.org + rss_limit: 50 + rabbitmq_host: localhost + rabbitmq_port: 5672 + rabbitmq_user: ~ + rabbitmq_password: ~ + rabbitmq_prefetch_count: 0 + redis_scheme: tcp + redis_host: localhost + redis_port: 6379 + redis_path: ~ + redis_password: ~ + sentry_dsn: ~ +''; + description = '' + Contents of the wallabag configuration file (parameters.yml) + ''; + }; + }; + }; + + + config = mkIf cfg.enable { + + services.phpfpm.pools."${poolName}" = { + user = "${cfg.user}"; + group = "nginx"; + settings = { + "listen" = "${phpfpmSocketName}"; + "listen.owner" = "nginx"; + "listen.group" = "nginx"; + "listen.mode" = "0600"; + "env[WALLABAG_DATA]" = "${cfg.dataDir}"; + "pm" = "dynamic"; + "pm.max_children" = "75"; + "pm.min_spare_servers" = "5"; + "pm.max_spare_servers" = "20"; + "pm.max_requests" = "10"; + "catch_workers_output" = "1"; + }; + }; + services.phpfpm.phpOptions = '' + max_execution_time = 120 + ''; + + services.nginx.enable = mkDefault true; + + services.nginx.virtualHosts."${cfg.hostName}" = { + root = "${cfg.package}/web"; + listen = [ { addr = "192.168.1.6"; port = 8080; } ]; + + extraConfig = '' + add_header X-Frame-Options SAMEORIGIN; + add_header X-Content-Type-Options nosniff; + add_header X-XSS-Protection "1; mode=block"; + ''; + + locations."/" = { + extraConfig = '' + try_files $uri /app.php$is_args$args; + ''; + }; + + locations."/assets".root = "${cfg.dataDir}/web"; + + locations."~ ^/app\\.php(/|$)" = { + extraConfig = '' + fastcgi_pass unix:${phpfpmSocketName}; + fastcgi_split_path_info ^(.+\.php)(/.*)$; + include ${pkgs.nginx}/conf/fastcgi_params; + + fastcgi_param SCRIPT_FILENAME ${cfg.package}/web/$fastcgi_script_name; + fastcgi_param DOCUMENT_ROOT ${cfg.package}/web; + fastcgi_read_timeout 120; + + internal; + ''; + }; + + locations."~ /(?!app)\\.php$" = { + extraConfig = '' + return 404; + ''; + }; + }; + + services.postgresql = { + enable = true; + + # Ensure the database, user, and permissions always exist + ensureDatabases = [ "wallabag" "wallabag_user" ]; + authentication = lib.mkForce '' + # Generated file; do not edit! + # TYPE DATABASE USER ADDRESS METHOD + local all all trust + host all wallabag 127.0.0.1/32 trust + ''; + ensureUsers = [ + { name = "wallabag"; + ensurePermissions."DATABASE wallabag" = "ALL PRIVILEGES"; + ensurePermissions."DATABASE wallabag_user" = "ALL PRIVILEGES"; + } + ]; + }; + + systemd.services.wallabag-install = { + description = "Wallabag install service"; + wantedBy = [ "multi-user.target" ]; + before = [ "phpfpm-wallabag.service" ]; + after = [ "mysql.service" "postgresql.service" ]; + path = with pkgs; [ coreutils php72 php72Packages.composer ]; + + serviceConfig = { + User = cfg.user; + Type = "oneshot"; + RemainAfterExit = "yes"; + PermissionsStartOnly = true; + }; + + preStart = '' + mkdir -p "${cfg.dataDir}" + chown ${cfg.user}:nginx "${cfg.dataDir}" + ''; + + script = '' + echo "Setting up wallabag files in ${cfg.dataDir} ..." + cd "${cfg.dataDir}" + + rm -rf var/cache/* + rm -f app + ln -sf ${appDir} app + ln -sf ${cfg.package}/composer.{json,lock} . + + export WALLABAG_DATA="${cfg.dataDir}" + if [ ! -f installed ]; then + php ${cfg.package}/bin/console --env=prod doctrine:database:create --if-not-exists --no-interaction + #php ${cfg.package}/bin/console --env=prod doctrine:migrations:migrate --no-interaction + # Until https://github.com/wallabag/wallabag/issues/3662 is fixed + yes no | php ${cfg.package}/bin/console --env=prod wallabag:install + touch installed + else + php ${cfg.package}/bin/console --env=prod doctrine:migrations:migrate --no-interaction + fi + php ${cfg.package}/bin/console --env=prod cache:clear + ''; + }; + }; + + meta = with stdenv.lib; { + maintainers = with maintainers; [ chickensoupwithrice ]; + }; +} diff --git a/modules/monitoring.nix b/modules/monitoring.nix new file mode 100644 index 00000000..c5683289 --- /dev/null +++ b/modules/monitoring.nix @@ -0,0 +1,53 @@ +{ config, pkgs, ... }: { + # grafana configuration + services.grafana = { + enable = true; + domain = "grafana.mossnet.lan"; + port = 2342; + addr = "127.0.0.1"; + }; + + # nginx reverse proxy + services.nginx.virtualHosts.${config.services.grafana.domain} = { + locations."/" = { + proxyPass = "http://127.0.0.1:${toString config.services.grafana.port}"; + proxyWebsockets = true; + }; + }; + + services.prometheus = { + enable = true; + port = 9001; + exporters = { + node = { + enable = true; + enabledCollectors = [ "systemd" ]; + port = 9002; + }; + }; + scrapeConfigs = [ + { + job_name = "bowl"; + static_configs = [{ + targets = [ "127.0.0.1:${toString config.services.prometheus.exporters.node.port}" ]; + }]; + } + ]; + }; + + services.loki = { + enable = true; + configFile = /var/loki-config.yaml; + }; + + systemd.services.promtail = { + description = "Promtail service for Loki"; + wantedBy = [ "multi-user.target" ]; + + serviceConfig = { + ExecStart = '' + ${pkgs.grafana-loki}/bin/promtail --config.file ${/var/promtail.yaml} + ''; + }; + }; +} diff --git a/modules/navidrome.nix b/modules/navidrome.nix new file mode 100644 index 00000000..be4fe9c5 --- /dev/null +++ b/modules/navidrome.nix @@ -0,0 +1,101 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.navidrome; + configFile = "/etc/navidrome/settings.json"; + dataFolder = "/var/lib/navidrome"; +in { + options = { + + services.navidrome = { + enable = mkEnableOption "Navidrome music server and streamer"; + + settings = lib.mkOption { + type = with types; attrsOf (oneOf [ int str ]); + default = {}; + example = literalExample '' + { + LogLevel = "INFO"; + BaseURL = "/music"; + ScanInterval = "10s"; + TranscodingCacheSize = "15MB"; + MusicFolder = "/data/music"; + }; + ''; + description = '' + Configuration for Navidrome, see for supported values. + ''; + }; + + user = mkOption { + type = types.str; + default = "navidrome"; + description = "User account under which Navidrome runs."; + }; + + group = mkOption { + type = types.str; + default = "navidrome"; + description = "Group account under which Navidrome runs."; + }; + + }; + }; + + config = mkIf cfg.enable { + + environment.etc."navidrome/settings.json".text = builtins.toJSON cfg.settings; + + services.navidrome.settings = { + DataFolder = dataFolder; + ConfigFile = configFile; + }; + + systemd.services.navidrome = { + description = "Navidrome Music Server and Streamer compatible with Subsonic/Airsonic"; + after = [ "remote-fs.target" "network.target" ]; + wantedBy = [ "multi-user.target" ]; + environment = { + ND_CONFIGFILE = configFile; + }; + serviceConfig = { + ExecStart = "${pkgs.navidrome}/bin/navidrome"; + WorkingDirectory = dataFolder; + TimeoutStopSec = "20"; + KillMode = "process"; + Restart = "on-failure"; + User = cfg.user; + Group = cfg.group; + DevicePolicy = "closed"; + NoNewPrivileges= " yes"; + PrivateTmp = "yes"; + PrivateUsers = "yes"; + ProtectControlGroups = "yes"; + ProtectKernelModules = "yes"; + ProtectKernelTunables = "yes"; + RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6"; + RestrictNamespaces = "yes"; + RestrictRealtime = "yes"; + SystemCallFilter = "~@clock @debug @module @mount @obsolete @privileged @reboot @setuid @swap"; + ReadWritePaths = dataFolder; + StateDirectory = baseNameOf dataFolder; + }; + }; + + users.users = optionalAttrs (cfg.user == "navidrome") ({ + navidrome = { + description = "Navidrome service user"; + name = cfg.user; + group = cfg.group; + isSystemUser = true; + }; + }); + + users.groups = optionalAttrs (cfg.group == "navidrome") ({ + navidrome = {}; + }); + + }; +} diff --git a/modules/nextcloud.nix b/modules/nextcloud.nix new file mode 100644 index 00000000..c1919b80 --- /dev/null +++ b/modules/nextcloud.nix @@ -0,0 +1,52 @@ +{ pkgs, config, ... }: +{ + services.nextcloud = { + enable = true; + hostName = "mossnet.lan"; + #home = "/data/nextcloud"; + + # Use HTTPS for links + https = false; + + # Auto-update Nextcloud Apps + autoUpdateApps.enable = true; + # Set what time makes sense for you + autoUpdateApps.startAt = "05:00:00"; + + config = { + # Further forces Nextcloud to use HTTPS + # overwriteProtocol = "https"; + + # Nextcloud PostegreSQL database configuration, recommended over using SQLite + dbtype = "pgsql"; + dbuser = "nextcloud"; + dbhost = "/run/postgresql"; # nextcloud will add /.s.PGSQL.5432 by itself + dbname = "nextcloud"; + dbpassFile = "/var/nextcloud-db-pass"; + + adminpassFile = "/var/nextcloud-admin-pass"; + adminuser = "admin"; + }; + }; + + # Enable PostgreSQL + services.postgresql = { + enable = true; + + # Ensure the database, user, and permissions always exist + ensureDatabases = [ "nextcloud" ]; + ensureUsers = [ + { name = "nextcloud"; + ensurePermissions."DATABASE nextcloud" = "ALL PRIVILEGES"; + } + ]; + }; + + # Ensure that postgres is running before running the setup + systemd.services."nextcloud-setup" = { + requires = ["postgresql.service"]; + after = ["postgresql.service"]; + }; + + networking.firewall.allowedTCPPorts = [ 80 443 ]; +} diff --git a/nvim.nix b/modules/nvim.nix similarity index 100% rename from nvim.nix rename to modules/nvim.nix diff --git a/modules/shaarli.nix b/modules/shaarli.nix new file mode 100644 index 00000000..d773bca6 --- /dev/null +++ b/modules/shaarli.nix @@ -0,0 +1,116 @@ +{ pkgs, config, ... }: +let + dataDir = "/var/www/shaarli-config"; + name = "shaarli"; +in +{ + services.nginx = { + enable = true; + virtualHosts = { + "links.mossnet.lan" = { + forceSSL = false; + enableACME = false; + root = "${dataDir}"; + #listen = [ { addr = "192.168.1.6"; port = 1234; } ]; + extraConfig = '' + index index.php; + ''; + locations = { + "/".extraConfig = '' + try_files $uri $uri/ index.php; + ''; + + "~ (index)\.php$".extraConfig = '' + fastcgi_split_path_info ^(.+\.php)(/.*)$; + if (!-f $document_root$fastcgi_script_name) { + return 404; + } + + fastcgi_pass unix:${config.services.phpfpm.pools."${name}".socket}; + fastcgi_index index.php; + + fastcgi_param QUERY_STRING $query_string; + fastcgi_param REQUEST_METHOD $request_method; + fastcgi_param CONTENT_TYPE $content_type; + fastcgi_param CONTENT_LENGTH $content_length; + + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_param SCRIPT_NAME $fastcgi_script_name; + fastcgi_param PATH_INFO $fastcgi_path_info; + fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info; + fastcgi_param REQUEST_URI $request_uri; + fastcgi_param DOCUMENT_URI $document_uri; + fastcgi_param DOCUMENT_ROOT $document_root; + fastcgi_param SERVER_PROTOCOL $server_protocol; + + fastcgi_param GATEWAY_INTERFACE CGI/1.1; + fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; + + fastcgi_param REMOTE_ADDR $remote_addr; + fastcgi_param REMOTE_PORT $remote_port; + fastcgi_param SERVER_ADDR $server_addr; + fastcgi_param SERVER_PORT $server_port; + fastcgi_param SERVER_NAME $server_name; + ''; + + "~ \.php$".extraConfig = '' + deny all; + ''; + + "^~ /tpl/".extraConfig = "alias ${pkgs.shaarli}/tpl/;"; + + "^~ /plugins/".extraConfig = "alias ${pkgs.shaarli}/plugins/;"; + + "~* \\.(?:ico|css|js|gif|jpe?g|png)$".extraConfig = '' + expires max; + add_header Pragma public; + add_header Cache-Control "public, must-revalidate, proxy-revalidate"; + ''; + }; + }; + }; + }; + + services.phpfpm = { + pools = { + "${name}" = { + user = "nginx"; + group = "nginx"; + #listen = "/run/phpfpm/php.sock"; + settings = { + "listen.owner" = "nginx"; + "listen.group" = "nginx"; + "user" = "nginx"; + "pm" = "dynamic"; + "pm.max_children" = "4"; + "pm.min_spare_servers" = "1"; + "pm.max_spare_servers" = "4"; + "pm.max_requests" = "32"; + "catch_workers_output" = "1"; + "php_admin_value[error_log]" = "/var/log/nginx/${name}-phpfpm-error.log"; + }; + }; + }; + }; + users.extraUsers."${name}" = { group = "${name}"; }; + users.extraGroups."${name}" = { }; + systemd.services.shaarli-install = { + serviceConfig.Type = "oneshot"; + wantedBy = [ "multi-user.target" ]; + script = '' + if [ ! -d "${dataDir}" ]; then + mkdir -p ${dataDir}/{cache,data,pagecache,tmp} + cp -R ${pkgs.shaarli}/data.orig/.htaccess ${dataDir}/cache/ + cp -R ${pkgs.shaarli}/data.orig/.htaccess ${dataDir}/data/ + cp -R ${pkgs.shaarli}/data.orig/.htaccess ${dataDir}/pagecache/ + cp -R ${pkgs.shaarli}/data.orig/.htaccess ${dataDir}/tmp/ + ln -S ${pkgs.shaarli}/* ${dataDir} + fi + chown -Rc nginx:nginx ${dataDir} + find ${dataDir} -type d ! -perm 0700 -exec chmod 0700 {} \; -exec chmod g-s {} \; + find ${dataDir} -type f ! -perm 0600 -exec chmod 0600 {} \; + ''; + }; + # TODO: Write the configuration file here? + networking.firewall.allowedTCPPorts = [ 1234 ]; +} diff --git a/modules/taskd.nix b/modules/taskd.nix new file mode 100644 index 00000000..f698a58b --- /dev/null +++ b/modules/taskd.nix @@ -0,0 +1,10 @@ +{ config, pkgs, ... }: + +{ + services.taskserver.enable = true; + services.taskserver.fqdn = "192.168.1.6"; + services.taskserver.listenHost = "192.168.1.6"; + services.taskserver.listenPort = 53589; + services.taskserver.organisations.mossnet.users = [ "anish" ]; +} + diff --git a/modules/wireguard.nix b/modules/wireguard.nix new file mode 100644 index 00000000..ebad01c3 --- /dev/null +++ b/modules/wireguard.nix @@ -0,0 +1,21 @@ +{ config, pkgs, ... }: + +{ + boot.extraModulePackages = with config.boot.kernelPackages; [ wireguard ]; + environment.systemPackages = [ pkgs.wireguard ]; + networking.wireguard.enable = true; + networking.wireguard.interfaces = { + wg0 = { + ips = [ "10.0.69.2/32" ]; + privateKeyFile = "/var/lib/wireguard/priv"; + + peers = [ + { # helix - server + publicKey = "{c1J4p63rD3IlszugMZiki7UBV3YmDdqa3DU4UejXzAI=}"; + allowedIPs = [ "10.0.69.1/24" ]; + endpoint = "sealight.xyz:60990"; + persistentKeepalive = 25; + } ]; + }; + }; +} diff --git a/pkgs/pkg-navidrome.nix b/pkgs/pkg-navidrome.nix new file mode 100644 index 00000000..5bcd3789 --- /dev/null +++ b/pkgs/pkg-navidrome.nix @@ -0,0 +1,9 @@ +{ config, lib, pkgs, ... }: +{ + services.navidrome.enable = true; + services.navidrome.settings = { + MusicFolder = "/data/music"; + Port = 4433; + }; + networking.firewall.allowedTCPPorts = [ 4433 ]; +} diff --git a/pkgs/pkg-rssBridge.nix b/pkgs/pkg-rssBridge.nix new file mode 100644 index 00000000..e606c187 --- /dev/null +++ b/pkgs/pkg-rssBridge.nix @@ -0,0 +1,30 @@ +{ lib, stdenv, fetchurl, config ? null, dataDir ? "/var/lib/shaarli" }: + +stdenv.mkDerivation rec { + name = "rssBridge-${version}"; + version = "2020-10-11"; + preferLocalBuild = true; + + src = fetchurl { + url = "https://github.com/RSS-Bridge/rss-bridge/archive/${version}.tar.gz"; + sha256 = ""; + }; + + phases = [ "installPhase" ]; + installPhase = '' + mkdir $out + tar xzf $src + cp -ra * $out/ + find $out -type d -exec chmod 0755 {} \; + find $out -type f -exec chmod 0644 {} \; + ln -s $dataDir $out + ''; + + meta = with stdenv.lib; { + description = "RSS-Bridge is a project to create RSS Feeds for websites that don't have one."; + #license = licenses.agpl3; + homepage = "https://github.com/RSS-Bridge/rss-bridge/"; + platforms = platforms.all; + maintainers = with stdenv.lib.maintainers; [ chickensoupwithrice ]; + }; +} diff --git a/pkgs/pkg-shaarli.nix b/pkgs/pkg-shaarli.nix new file mode 100644 index 00000000..be780707 --- /dev/null +++ b/pkgs/pkg-shaarli.nix @@ -0,0 +1,34 @@ +{ lib, stdenv, fetchurl, config ? null, dataDir ? "/var/lib/shaarli" }: + +stdenv.mkDerivation rec { + name = "shaarli-${version}"; + version = "0.11.1"; + preferLocalBuild = true; + + src = fetchurl { + url = "https://github.com/shaarli/Shaarli/releases/download/v0.11.1/shaarli-v${version}-full.tar.gz"; + sha256 = "1psijcmi24hk0gxh1zdsm299xj11i7find2045nnx3r96cgnwjpn"; + }; + + phases = [ "installPhase" ]; + installPhase = '' + mkdir $out + tar xzf $src + cp -ra Shaarli/. $out/ + find $out -type d -exec chmod 0755 {} \; + find $out -type f -exec chmod 0644 {} \; + for a in cache data pagecache tmp; do + mv $out/$a $out/$a.orig + ln -s "${dataDir}/$a" $out/$a + done + ''; + + meta = with stdenv.lib; { + description = ""; + # License is complicated... + #license = licenses.agpl3; + homepage = "https://github.com/shaarli/Shaarli"; + platforms = platforms.all; + maintainers = with stdenv.lib.maintainers; [ tokudan ]; + }; +} diff --git a/pkgs/pkg-wallabag.nix b/pkgs/pkg-wallabag.nix new file mode 100644 index 00000000..8e645794 --- /dev/null +++ b/pkgs/pkg-wallabag.nix @@ -0,0 +1,9 @@ +{ pkgs, config, lib, ... }: + +{ + services.wallabag = { + enable = true; + hostName = "192.168.1.6:8080"; + }; + networking.firewall.allowedTCPPorts = [ 8080 ]; +} diff --git a/unstable.nix b/pkgs/unstable.nix similarity index 100% rename from unstable.nix rename to pkgs/unstable.nix diff --git a/cozette.nix b/reference/cozette.nix similarity index 100% rename from cozette.nix rename to reference/cozette.nix diff --git a/reference/networking.nix b/reference/networking.nix new file mode 100644 index 00000000..6ed28803 --- /dev/null +++ b/reference/networking.nix @@ -0,0 +1,12 @@ +{ config, pkgs, ... }: +{ + networking.interfaces.enp3s0.ipv4.addresses = [ { + address = "192.168.1.6"; + prefixLength = 24; + } ]; + networking.nameservers = [ "1.1.1.1" ]; + networking.defaultGateway = "192.168.1.1"; + environment.systemPackages = [ pkgs.mosh ]; + programs.mosh.enable = true; + #config.nssDatabase.hosts = [ "mdns_minimal" "[NOTFOUND=return]" ]; +} diff --git a/reference/shaarli-broken.nix b/reference/shaarli-broken.nix new file mode 100644 index 00000000..1541149c --- /dev/null +++ b/reference/shaarli-broken.nix @@ -0,0 +1,78 @@ +{ config, pkgs, ... }: +let + app = "shaarli"; + dataDir = "/var/www/${app}"; +in { + services.nginx = { + enable = true; + virtualHosts = { + "192.168.1.6:1232" = { + forceSSL = false; + enableACME = false; + #root = pkgs.shaarli; + root = dataDir; + listen = [ { addr = "192.168.1.6"; port = 1232; } ]; + extraConfig = '' + index index.php; + ''; + locations = { + "/".index = "index.php"; + + "~ /\\.".extraConfig = '' + log_not_found off; + deny all; + ''; + + "~ (index)\\.php$".extraConfig = '' + try_files $uri =404 + include ${pkgs.nginx}/conf/fastcgi.conf; + fastcgi_split_path_info ^(.+\.php)(/.*)$; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_param SHAARLI_CONFIG /var/www/shaarli/config; + + fastcgi_pass unix:${config.services.phpfpm.pools.${app}.socket}; + fastcgi_index index.php; + ''; + + "^~ /tpl/".extraConfig = "alias ${pkgs.shaarli}/tpl/;"; + + "~ \\.php$".extraConfig = '' + deny all; + ''; + + "^~ /plugins/".extraConfig = "alias ${pkgs.shaarli}/plugins/;"; + + "~* \\.(?:ico|css|js|gif|jpe?g|png)$".extraConfig = '' + expires max; + add_header Pragma public; + add_header Cache-Control "public, must-revalidate, proxy-revalidate"; + ''; + }; + }; + }; + }; + services.phpfpm.pools.${app} = { + user = app; + #listen = "/run/phpfpm/shaarli.sock"; + settings = { + "listen.owner" = config.services.nginx.user; + "pm" = "dynamic"; + "pm.max_children" = 4; + "pm.start_servers" = 2; + "pm.min_spare_servers" = 1; + "pm.max_spare_servers" = 4; + "pm.max_requests" = 32; + "php_admin_value[error_log]" = "stderr"; + "php_admin_flag[log_errors]" = true; + }; + }; + systemd.services.nginx.serviceConfig.ReadWritePaths = [ "/var/www" ]; + users.users.${app} = { + isSystemUser = true; + createHome = true; + home = dataDir; + group = app; + }; + users.groups.${app} = {}; + networking.firewall.allowedTCPPorts = [ 1232 ]; +} diff --git a/reference/shaarli-docker.nix b/reference/shaarli-docker.nix new file mode 100644 index 00000000..f2193fcf --- /dev/null +++ b/reference/shaarli-docker.nix @@ -0,0 +1,9 @@ +{ pkg, config, lib, ... }: +{ + docker-containers."shaarli" = { + image = "shaarli/shaarli"; + volumes = [ "shaarli:/var/lib/shaarli/data/" ]; + ports = [ "1233:80" ]; + }; + networking.firewall.allowedTCPPorts = [ 1233 ]; +} diff --git a/reference/shaarli-tokudan.nix b/reference/shaarli-tokudan.nix new file mode 100644 index 00000000..8a3c3fca --- /dev/null +++ b/reference/shaarli-tokudan.nix @@ -0,0 +1,97 @@ +{ config, lib, pkgs, ... }: + +let + phppoolName = "shaarli"; + dataDir = "/var/lib/shaarli"; + vhost = "192.168.1.6:1232"; + + shaarli = pkgs.callPackage ./pkg-shaarli.nix { + inherit dataDir; + }; +in +{ + services.nginx.virtualHosts."${vhost}" = { + forceSSL = false; + enableACME = false; + root = "${dataDir}"; + listen = [ { addr = "192.168.1.6"; port = 1232; } ]; + extraConfig = '' + index index.php; + ''; + locations."/" = { + extraConfig = '' + try_files _ /index.php$is_args$args;"; + ''; + }; + locations."~ (index)\\.php$" = { + extraConfig = '' + fastcgi_split_path_info ^(.+\.php)(/.*)$; + if (!-f $document_root$fastcgi_script_name) { + return 404; + } + + fastcgi_pass unix:${config.services.phpfpm.pools.shaarli.socket}; + fastcgi_index index.php; + + fastcgi_param QUERY_STRING $query_string; + fastcgi_param REQUEST_METHOD $request_method; + fastcgi_param CONTENT_TYPE $content_type; + fastcgi_param CONTENT_LENGTH $content_length; + + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_param SCRIPT_NAME $fastcgi_script_name; + fastcgi_param PATH_INFO $fastcgi_path_info; + fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info; + fastcgi_param REQUEST_URI $request_uri; + fastcgi_param DOCUMENT_URI $document_uri; + fastcgi_param DOCUMENT_ROOT $document_root; + fastcgi_param SERVER_PROTOCOL $server_protocol; + + fastcgi_param GATEWAY_INTERFACE CGI/1.1; + fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; + + fastcgi_param REMOTE_ADDR $remote_addr; + fastcgi_param REMOTE_PORT $remote_port; + fastcgi_param SERVER_ADDR $server_addr; + fastcgi_param SERVER_PORT $server_port; + fastcgi_param SERVER_NAME $server_name; + + fastcgi_param HTTPS $https; + ''; + }; + }; + services.phpfpm.pools.shaarli = { + user = "shaarli"; + group = "shaarli"; + settings = { + "listen.owner" = "nginx"; + "listen.group" = "nginx"; + "user" = "shaarli"; + "pm" = "dynamic"; + "pm.max_children" = "75"; + "pm.min_spare_servers" = "5"; + "pm.max_spare_servers" = "20"; + "pm.max_requests" = "10"; + "catch_workers_output" = "1"; + }; + }; + users.extraUsers.shaarli = { group = "shaarli"; home = dataDir; }; + users.extraGroups.shaarli = { }; + systemd.services.shaarli-install = { + serviceConfig.Type = "oneshot"; + wantedBy = [ "multi-user.target" ]; + script = '' + if [ ! -d "${dataDir}" ]; then + mkdir -p ${dataDir}/{cache,data,pagecache,tmp} + cp -R ${shaarli}/data.orig/.htaccess ${dataDir}/cache/ + cp -R ${shaarli}/data.orig/.htaccess ${dataDir}/data/ + cp -R ${shaarli}/data.orig/.htaccess ${dataDir}/pagecache/ + cp -R ${shaarli}/data.orig/.htaccess ${dataDir}/tmp/ + fi + chown -Rc shaarli:shaarli ${dataDir} + find ${dataDir} -type d ! -perm 0700 -exec chmod 0700 {} \; -exec chmod g-s {} \; + find ${dataDir} -type f ! -perm 0600 -exec chmod 0600 {} \; + ''; + }; + networking.firewall.allowedTCPPorts = [ 1232 ]; +} diff --git a/reference/shiori.nix b/reference/shiori.nix new file mode 100644 index 00000000..a1dfde45 --- /dev/null +++ b/reference/shiori.nix @@ -0,0 +1,7 @@ +{ pkgs, config, lib, ... }: +{ + services.shiori.enable = true; + services.shiori.address = "192.168.1.6"; + services.shiori.port = 1234; + networking.firewall.allowedTCPPorts = [ 1234 ]; +} diff --git a/reference/test-nginx.nix b/reference/test-nginx.nix new file mode 100644 index 00000000..69c480f2 --- /dev/null +++ b/reference/test-nginx.nix @@ -0,0 +1,24 @@ +{ pkgs, config, lib, ... }: + +let + vhost = "192.168.1.6:1232"; +in +{ + services.nginx.virtualHosts."${vhost}" = { + forceSSL = false; + enableACME = false; + root = "/var/lib/test"; + listen = [ { addr = "192.168.1.6"; port = 1232; } ]; + extraConfig = '' + index index.html; + ''; + + locations."/" = { + extraConfig = '' + try_files $uri $uri/ index.html; + ''; + }; + }; + + networking.firewall.allowedTCPPorts = [ 1232 ]; +} diff --git a/reference/wallabag-docker.nix b/reference/wallabag-docker.nix new file mode 100644 index 00000000..4bd844a1 --- /dev/null +++ b/reference/wallabag-docker.nix @@ -0,0 +1,52 @@ +{ pkg, config, lib, ... }: +{ + docker-containers."wallabag-db" = { + image = "postgres"; + environment = { + "POSTGRES_PASSWORD" = "wallaroot"; + "POSTGRES_USER" = "postgres"; + }; + extraDockerOptions = [ "--network=wallabag-br" ]; + volumes = [ "/opt/wallabag/data:/var/www/wallabag" ]; + }; + + docker-containers."wallabag" = { + image = "wallabag/wallabag"; + ports = [ "800:80" ]; + #volumes = [ "/opt/wallabag/data:/var/www/wallabag/data" "/opt/wallabag/images:/var/www/wallabag/web/assets/images" ]; + environment = { + "SYMFONY__ENV__DOMAIN_NAME" = "http://192.168.1.6:800"; + "POSTGRES_PASSWORD" = "wallaroot"; + "POSTGRES_USER" = "postgres"; + "SYMFONY__ENV__DATABASE_DRIVER" = "pdo_pgsql"; + "SYMFONY__ENV__DATABASE_DRIVER_CLASS" = "Wallabag\\CoreBundle\\Doctrine\\DBAL\\Driver\\CustomPostgreSQLDriver"; + "SYMFONY__ENV__DATABASE_HOST" = "wallabag-db"; + "SYMFONY__ENV__DATABASE_PORT" = "5432"; + "SYMFONY__ENV__DATABASE_NAME" = "wallabag"; + "SYMFONY__ENV__DATABASE_USER" = "wallabag"; + "SYMFONY__ENV__DATABASE_PASSWORD" = "wallapass"; + #"SYMFONY__ENV__DATABASE_CHARSET" = "utf8mb4"; + }; + extraDockerOptions = [ "--network=wallabag-br" ]; + }; + + systemd.services.init-wallabag-docker-br = { + description = "Create the network bridge wallabag."; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + + serviceConfig.Type = "oneshot"; + script = let dockercli = "${config.virtualisation.docker.package}/bin/docker"; + in '' + # Put a true at the end to prevent getting non-zero return code, which will + # crash the whole service. + check=$(${dockercli} network ls | grep "wallabag-br" || true) + if [ -z "$check" ]; then + ${dockercli} network create wallabag-br + else + echo "wallabag-br already exists in docker" + fi + ''; + }; + networking.firewall.allowedTCPPorts = [ 800 ]; +} diff --git a/reference/wallabag.nix b/reference/wallabag.nix new file mode 100644 index 00000000..d0e26f92 --- /dev/null +++ b/reference/wallabag.nix @@ -0,0 +1,120 @@ +{ pkgs, config, lib, ... }: + +let + phppoolName = "wallabag"; + dataDir = "/var/lib/wallabag"; + vhost = "read.mossnet.local"; +in +{ + services.nginx.virtualHosts."${vhost}" = { + forceSSL = false; + enableACME = false; + root = "/var/lib/wallabag/web"; + listen = [ { addr = "192.168.1.6"; port = 800; } ]; + + locations."/" = { + extraConfig = '' + try_files $uri /app.php$is_args$args; + ''; + }; + + locations."/assets".root = "${dataDir}/web"; + + locations."~ ^/app\.php(/|$)" = { + extraConfig = '' + include ${pkgs.nginx}/conf/fastcgi_params; + fastcgi_split_path_info ^(.+\.php)(/.*)$; + if (!-f $document_root$fastcgi_script_name) { + return 404; + } + + fastcgi_pass unix:${config.services.phpfpm.pools."${phppoolName}".socket}; + fastcgi_param SCRIPT_FILENAME {pkgs.wallabag}/web/$fastcgi_script_name; + fastcgi_param DOCUMENT_ROOT {pkgs.wallabag}/web; + ''; + }; + + locations."~ \.php$" = { + extraConfig = '' + return 404; + ''; + }; + }; + services.postgresql = { + enable = true; + + # Ensure the database, user, and permissions always exist + ensureDatabases = [ "wallabag" ]; + ensureUsers = [ + { name = "wallabag"; + ensurePermissions."DATABASE wallabag" = "ALL PRIVILEGES"; + } + ]; + }; + services.phpfpm.pools."${phppoolName}" = { + user = "wallabag"; + group = "wallabag"; + phpEnv."WALLABAG_DATA" = "/var/lib/wallabag"; + phpEnv."PATH" = lib.makeBinPath [ pkgs.php ]; + settings = { + "listen.owner" = "nginx"; + "listen.group" = "nginx"; + "user" = "wallabag"; + "pm" = "dynamic"; + "pm.max_children" = "75"; + "pm.min_spare_servers" = "5"; + "pm.max_spare_servers" = "20"; + "pm.max_requests" = "10"; + "catch_workers_output" = "1"; + }; + }; + + systemd.services.wallabag-install = { + description = "Wallabag install service"; + wantedBy = [ "multi-user.target" ]; + before = [ "phpfpm-wallabag.service" ]; + after = [ "mysql.service" "postgresql.service" ]; + path = [ pkgs.coreutils pkgs.php73 pkgs.php73Packages.composer ]; + + serviceConfig = { + User = "wallabag"; + Type = "oneshot"; + RemainAfterExit = "yes"; + PermissionsStartOnly = true; + }; + + preStart = '' + mkdir -p "${dataDir}" + chown wallabag:nginx "${dataDir}" + ''; + + script = '' + echo "Setting up wallabag files in ${dataDir} ..." + cd "${dataDir}" + + rm -rf var/cache/* + rm -f ${dataDir}/app + rm -f ${dataDir}/bin + ln -sf ${pkgs.wallabag}/app app + ln -sf ${pkgs.wallabag}/composer.{json,lock} . + ln -sf ${pkgs.wallabag}/bin/ bin + + export WALLABAG_DATA="${dataDir}" + if [ ! -f installed ]; then + php /var/lib/wallabag/bin/console --env=prod doctrine:database:create --if-not-exists --no-interaction + php /var/lib/wallabag/bin/console --env=prod doctrine:migrations:migrate --no-interaction + # Until https://github.com/wallabag/wallabag/issues/3662 is fixed + yes no | php /var/lib/wallabag/bin/console --env=prod wallabag:install + touch installed + else + php ${pkgs.wallabag}/bin/console --env=prod doctrine:migrations:migrate --no-interaction + fi + php ${pkgs.wallabag}/bin/console --env=prod cache:clear + ''; + }; + + users.extraUsers.wallabag = { group = "wallabag"; }; + users.extraGroups.wallabag = { }; + + networking.firewall.allowedTCPPorts = [ 800 ]; +}