diff --git a/README.md b/README.md index 0b24852..7894f1b 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,26 @@ # hacc nixfiles -welcome to hacc nixfiles (haccfiles). this is the code describing our nix-based infrastructure. +Welcome to the hacc nixfiles (haccfiles). This is how we configure (most of) +our infrastructure. -## structure +## General layout - `flake.nix`: Entrypoint & dependencies -- `common/`: configuration common to all hosts - `modules/`: home-grown modules for hacc-specific services -- `pkgs/`: packages we built and don't want to upstream -- `hosts/`: configuration.nix per host (currently there's only one of those) -- `services/`: all services we run; imported in appropriate host config -- `websites/`: static websites we deploy somewhere +- `pkgs/`: packages we need which aren't in nixpkgs +- `websites/`: static websites hosted by us +- `common/`: meta-level config, reusable across machines +- `parsons/`: our sole server, its config & the services it runs -## working with the haccfiles +Right now, we only have a single host. We might add more again in the future. + +## Working with this repo You will need a flake-enabled nix installation, and have your ssh config set up so that `ssh parsons` will connect to `parsons.hacc.space`. +### Deploying remotely + It's recommended to use [deploy_rs](https://github.com/serokell/deploy-rs): ~~~shell deploy .#parsons -k [--dry-activate] @@ -28,30 +32,13 @@ nixos-rebuild --flake .#parsons --target-host parsons \ --use-remote-sudo --use-substitutes [test|switch|dry-activate] ~~~ -If for some reason you have `nix` but not `nixos-rebuild`, you can still build the -system closure using: +### Re-deploying on parsons itself + +Simply do: ~~~shell -nix build .#nixosConfigurations.parsons.config.system.build.toplevel +nixos-rebuild --flake .#parsons [test|switch|dry-activate] ~~~ -(but you might have trouble deploying it) - -## Secret management - -We use [sops-nix](https://github.com/Mic92/sops-nix) to manage secrets which we'd -like to have in Git but don't want to be public. Entires in `secrets.yaml` are -encrypted for each of the age keys listed in `.sops.yaml`, which are themselves -derived from ssh keys. - -For the initial set up, please take a look at the sops-nix Readme file. - -To edit the secrets file, just use `sops secrets.yaml`, which will decrypt the -file & open it in your $EDITOR, then re-encrypt it when you're done. - -To add a new key, use `ssh-to-age` to convert your ssh key to age, and add it to -`sops.yaml`. Then do `sops updatekeys secrets.yaml` to re-encrypt the file for -the new set of keys. - ## Working on websites Websites are exposed as flake outputs: if you're working on a website & want to diff --git a/docs/_index.md b/docs/_index.md new file mode 100644 index 0000000..9cf3041 --- /dev/null +++ b/docs/_index.md @@ -0,0 +1,7 @@ ++++ +title = "hacc infra documentation" +page_template = "doc-page.html" +sort_by="title" ++++ + + diff --git a/docs/auth.md b/docs/auth.md new file mode 100644 index 0000000..6efed0e --- /dev/null +++ b/docs/auth.md @@ -0,0 +1,10 @@ ++++ +title = "Authentication" +categories = [ "services", "uffd" ] ++++ + +We use [uffd](https://git.cccv.de/uffd/uffd) for our SSO, for better or worse. +Mostly for worse. + + + diff --git a/docs/domains.md b/docs/domains.md new file mode 100644 index 0000000..237a876 --- /dev/null +++ b/docs/domains.md @@ -0,0 +1,20 @@ ++++ +title = "Domains" +categories = [ "domains", "meta" ] ++++ + +Perhaps too many of them. + +## Domains + +| domain | mc | status | date | reseller | owner | custody | +| :------------------- | :-: | :-----: | :------: | :---------- | :--------- | :-----: | +| 4future.dev | yes | | | | | hacc e.V. | +| infra4future.de | yes | | | | | hacc e.V. | +| hacc.space | yes | | | | | hacc e.V. | +| hacc.earth | yes | | | | | hacc e.V. | +| hacc.media | yes | | | | | hacc e.V. | +| hacc.wiki | no | | | | | | + +mc = managed by cloudflare +status = (renewl | autorenewl | expires) diff --git a/docs/hostnames.md b/docs/hostnames.md new file mode 100644 index 0000000..ea1dcf8 --- /dev/null +++ b/docs/hostnames.md @@ -0,0 +1,16 @@ ++++ +title = "Hostname schema" ++++ + +[Badass Anarchist Women](https://listverse.com/2018/09/27/10-absolutely-badass-anarchist-women-who-challenged-the-system/) +- keller +- deCleyre +- davidNeel +- leGuin +- [parsons](../parsons) +- ohair +- berneri +- michel +- sanger +- goldman + diff --git a/docs/lxc.md b/docs/lxc.md new file mode 100644 index 0000000..a4d354f --- /dev/null +++ b/docs/lxc.md @@ -0,0 +1,17 @@ ++++ +title = "LXC" +categories = [ "lxc" ] ++++ + +Some things don't easily run on NixOS. For these we have LXC containers running +debian. + +Right now, only onlyoffice is left. + +## Useful commands + - login to a container as root with a usable shell + `lxc-attach -n -- /usr/bin/sudo -i` + - restarting the keycloak and ldap containers + `lxc-stop -n && lxc-start -n ` + - restarting their network bridge: + `systemctl restart lxcbr0-netdev.services` diff --git a/docs/rebooting.md b/docs/rebooting.md new file mode 100644 index 0000000..c7b57e1 --- /dev/null +++ b/docs/rebooting.md @@ -0,0 +1,18 @@ ++++ +title = "Rebooting Parsons" +categories = [ "nix" ] ++++ + +## Check integrity after unexpected shutdown +These steps are only required if the server shut down unexpectedly or you suspect tampering. + +TODO + +## Unlock full disk encryption +Connection to the server via the command listed in the shared password manager. +Only the Vorstand has access to it! + +Enter the passwords for dpool and zroot. + +If both are correct, you will be disconnected and the server continues the boot sequence. +The server should be up after about minute. Please check all services for availability. diff --git a/docs/secrets.md b/docs/secrets.md new file mode 100644 index 0000000..31df55b --- /dev/null +++ b/docs/secrets.md @@ -0,0 +1,21 @@ ++++ +title = "Secrets" +categories = [ "services", "sops" ] ++++ + +## Secret management + +We use [sops-nix](https://github.com/Mic92/sops-nix) to manage secrets which we'd +like to have in Git but don't want to be public. Entries in `secrets.yaml` are +encrypted for each of the age keys listed in `.sops.yaml`, which are themselves +derived from ssh keys. + +For the initial set up, please take a look at the sops-nix Readme file. + +To edit the secrets file, run `sops secrets.yaml`, which will decrypt the +file & open it in your $EDITOR, then re-encrypt it when you're done. + +To add a new key, use `ssh-to-age` to convert your ssh key to age, and add it to +`sops.yaml`. Then do `sops updatekeys secrets.yaml` to re-encrypt the file for +the new set of keys. + diff --git a/docs/services/_index.md b/docs/services/_index.md new file mode 100644 index 0000000..59a0b1e --- /dev/null +++ b/docs/services/_index.md @@ -0,0 +1,5 @@ ++++ +title = "Services" +sort_by = "title" +page_template = "doc-page.html" ++++ diff --git a/docs/services/acme.md b/docs/services/acme.md new file mode 100644 index 0000000..f1c8a82 --- /dev/null +++ b/docs/services/acme.md @@ -0,0 +1,19 @@ ++++ +title = "ACME / letsencrypt" +categories = [ "domain", "https", "ssl", "tls", "Certificates" ] ++++ + + +# Usage + +We use the ACME module's nginx integration for basically everything. Beware of +rate limits when redeploying lots of things at once! Let's Encrypt is a little +picky about those. + + +## Workarounds & peculiar configuration choices + +Certs live under `/var/lib/acme/` + +If you need to remove a cert for whatever reason, be aware that there is a +hidden `.lego` folder, that contains state as well diff --git a/docs/services/hedgedoc.md b/docs/services/hedgedoc.md new file mode 100644 index 0000000..83b6d42 --- /dev/null +++ b/docs/services/hedgedoc.md @@ -0,0 +1,68 @@ ++++ +title = "hedgedoc" +taxonomies.categories = [ "services" ] ++++ + + +hegedoc was once called codiMD, so container, config and users are still called codimd. + +**Do NOT change this** unless you're sure what you're doing. + +We have two instances: + - `pad-hacc`/pad.hacc.space is connected to our SSO/uffd + - `pad-i4f`/pad.infra4future.de is not connected to our SSO and meant to be more public + +## Basic Troubleshooting + +Usually if hedgedoc dies, it's because postgresql wasn't there yet. Just restart +hedgedoc. + +## More Troubles +log into the container and take a look at the logs + +~~~shell +sudo nixos-container root-login codimd +journalctl -e +~~~ + +### fixing failed database upgrades + +see https://docs.hedgedoc.org/guides/migration-troubleshooting/ (copied below +for convenience?): + +In some cases, HedgeDoc might apply migrations without correctly saving the +progress. It will then refuse to start with "already exists"-errors like +ERROR: type "enum_Notes_permission" already exists. + +Get the name of the failing migration and append .js to it. For example, if +you encounter this error: + +~~~ +== 20180306150303-fix-enum: migrating ======= + +ERROR: type "enum_Notes_permission" already exists +~~~ + +the name of the failed migration would be 20180306150303-fix-enum.js. + +The SQL-statement may look like this: + +~~~ +INSERT INTO "SequelizeMeta" (name) VALUES ('20180306150303-fix-enum.js'); +~~~ + +Make sure HedgeDoc does not run and insert the name into the SequelizeMeta table. +Enter the container switch to the postgres user, open psql and commect to the +codimd database: + +~~~shell +su postgres +psql +\l +\c codimd +UN adjusted SQL STAMEMENT from above ] +\q +~~~ + +Start HedgeDoc again and observe if it starts correctly. It may be necessary to +repeat this process and insert multiple migrations into the SequelizeMeta table. diff --git a/docs/services/mail.md b/docs/services/mail.md new file mode 100644 index 0000000..b6814a2 --- /dev/null +++ b/docs/services/mail.md @@ -0,0 +1,65 @@ ++++ +title = "mail" +taxonomies.categories = [ "services" ] ++++ + +Mail is not connected to our SSO! + +## adding a mail account +- We use `@hacc.space` for our mails +- `@infra4future.de` is reserved for services, old user accounts will be + forwarded & logins disabled +- choose a name (no aliases or other names can be the same) +- generate a sha-512 password hash ```mkpasswd -m sha-512``` - **never add an + unhashed password!** +- add your account to `loginAccounts =` in `//parsons/mail.nix` +- build and redeploy parsons + +**example:** +``` +zwoelfontheshelf@hacc.space" = { + hashedPassword = "$6$ISAaU8X6D$oGKe9WXDWrRpGzHUEdxrxdtgvzuGOkBMuDc82IZhegpsv1bqd550FhZZrI40IjZTA5Hy2MZ8j/0efpnQ4fOQH0"; +}; +``` + +## adding to a forward address +- add the mail address to the corresponding `extraVirtualAliases =` +- build and redeploy parsons + +## adding a forward address +- add the address to `extraVirtualAliases =` +- add the addresses it should forward to +- build and redeploy parsons + +**example:** +``` +"himmel@hacc.space" = [ + "hexchen@hacc.space" + "zauberberg@hacc.space" +]; +``` + +## sending & receiving mail + +### as a user +- Your mail client should auto configure correctly + +~~~ +mailserver: mail.hacc.space (everywhere) +username: $your_mail_address +sending via smtp: port 587 or 465 +recieving + imap: port 993 +TLS and STARTTLS are supported +~~~ + +- You can send mail as you and any alias you receive mail from. Set a second Identity in your e-mail client + +### as an application +- mailserver: `mail.hacc.space` +- Do **not** use port 25. It's for server to server communication only. +- Use smtp ports `587` or `465` +- enable TLS if possible +- only send mail from `noreply@infra4future.de` +- Password is somewhere (TODO!) + diff --git a/docs/services/mumble.md b/docs/services/mumble.md new file mode 100644 index 0000000..7591723 --- /dev/null +++ b/docs/services/mumble.md @@ -0,0 +1,40 @@ ++++ +title = "mumble" +taxonomies.categories = [ "mumble" ] ++++ + + +[offical Docmuentation](https://wiki.mumble.info/wiki/Main_Page) + +Mumble's server is called murmur, but the naming is inconsistent. Sometimes +it's also just called mumble server. + +# Usage + +## registration +Users need to be registered to join any other channel than public. +An already registered user has to register them with the server. +1. right click on the username +2. choose register in the menu. Done. + +## restricted channels +Every channel in the hacc category except for plenum can only be accessed by +members of the hacc group. + +## adding users to a group +Only admins can edit groups, and only registered users can be added to groups. +1. right click on the Root channel +2. select Edit... +2. In Groups select $groupname +3. make the change you want to make +4. click "OK" + +# Config details +- the server is not registered with mumble & not on the public server list +- the bitrate is set to 128kb/s; otherwise the client would complain that the + server bitrate is less then the configured (default) in its local settings + +# Hacks +- murmur needs a TLS cert, which we get via the ACME module +- there's a funny group setup so that hopefully murmurd can read the cert +- this seems to work fine now, but was some source of trouble in the past diff --git a/docs/services/service.template.md b/docs/services/service.template.md new file mode 100644 index 0000000..b8a2517 --- /dev/null +++ b/docs/services/service.template.md @@ -0,0 +1,18 @@ ++++ +title = "$Service Name" +draft = true ## Remove this line to make file appear on website ++++ + + + +# Usage + + +# Config Notes + + +## Updating + + +# Hacks + diff --git a/docs/snapshots.md b/docs/snapshots.md new file mode 100644 index 0000000..23f506c --- /dev/null +++ b/docs/snapshots.md @@ -0,0 +1,24 @@ ++++ +title = "Use ZFS snapshot" +taxonomies.categories = [ "zfs", "snapshot", "filesystem", "backup", "update", "upgrade" ] ++++ + +## Make a ZFS snapshot +~~~shell +sudo zfs snapshot zroot/safe/persist@ +~~~ + +## Rollback + +### single files +The snapshots can be accessed under `/.zfs/snapshot/...` + +### fully +~~~shell +sudo zfs rollback zroot/safe/persist@ +~~~ + +## Delete a ZFS snapshot +~~~shell +sudo zfs destroy zroot/safe/persist@ +~~~ diff --git a/flake.nix b/flake.nix index bfc8dd8..c57ae6e 100644 --- a/flake.nix +++ b/flake.nix @@ -71,7 +71,7 @@ nixosConfigurations.parsons = nixpkgs.lib.nixosSystem { system = "x86_64-linux"; modules = [ - ./hosts/parsons/configuration.nix + ./parsons/configuration.nix sops-nix.nixosModules.sops { nixpkgs.pkgs = pkgs; } { environment.etc."haccfiles".source = self.outPath; } @@ -98,7 +98,10 @@ deploy-rs.lib; packages.x86_64-linux = - self.nixosConfigurations.parsons.config.hacc.websites.builders; + let + websites = self.nixosConfigurations.parsons.config.hacc.websites.builders; + in + { docs = websites."docs.hacc.space"; } // websites; }; } diff --git a/hosts/parsons/configuration.nix b/parsons/configuration.nix similarity index 78% rename from hosts/parsons/configuration.nix rename to parsons/configuration.nix index 31381d4..9366ef2 100644 --- a/hosts/parsons/configuration.nix +++ b/parsons/configuration.nix @@ -2,34 +2,27 @@ { imports = [ - ../../common + ../common ./hardware.nix modules.encboot modules.network.nftables modules.nftnat sources.nix-hexchen.nixosModules.profiles.nopersist - - ../../services/nextcloud.nix - ../../services/mattermost.nix - ../../services/thelounge.nix - ../../services/murmur.nix - ../../services/hedgedoc-hacc.nix - ../../services/hedgedoc-i4f.nix - ../../services/mail.nix - ../../services/gitea.nix - ../../services/nginx-pages.nix - ../../services/vaultwarden.nix - ../../services/tracktrain.nix - ../../services/uffd.nix - + ./nextcloud.nix + ./mattermost.nix + ./murmur.nix + ./hedgedoc-hacc.nix + ./hedgedoc-i4f.nix + ./mail.nix + ./gitea.nix + ./nginx-pages.nix + ./vaultwarden.nix + ./tracktrain.nix + ./uffd.nix ./lxc.nix ]; hexchen.bindmounts."/var/lib/acme" = "/persist/var/lib/acme"; - # fileSystems."/var/lib/acme" = { - # device = "/persist/var/lib/acme"; - # fsType = "bind"; - # }; hexchen.encboot = { enable = true; @@ -37,7 +30,7 @@ networkDrivers = [ "igb" ]; }; - sops.defaultSopsFile = ../../secrets.yaml; + sops.defaultSopsFile = ../secrets.yaml; sops.age.sshKeyPaths = [ "/persist/ssh/ssh_host_ed25519_key" ]; boot.loader.grub.enable = true; diff --git a/services/gitea.nix b/parsons/gitea.nix similarity index 100% rename from services/gitea.nix rename to parsons/gitea.nix diff --git a/hosts/parsons/hardware.nix b/parsons/hardware.nix similarity index 100% rename from hosts/parsons/hardware.nix rename to parsons/hardware.nix diff --git a/services/hedgedoc-hacc.nix b/parsons/hedgedoc-hacc.nix similarity index 100% rename from services/hedgedoc-hacc.nix rename to parsons/hedgedoc-hacc.nix diff --git a/services/hedgedoc-i4f.nix b/parsons/hedgedoc-i4f.nix similarity index 100% rename from services/hedgedoc-i4f.nix rename to parsons/hedgedoc-i4f.nix diff --git a/hosts/parsons/lxc.nix b/parsons/lxc.nix similarity index 100% rename from hosts/parsons/lxc.nix rename to parsons/lxc.nix diff --git a/services/mail.nix b/parsons/mail.nix similarity index 100% rename from services/mail.nix rename to parsons/mail.nix diff --git a/services/mattermost.nix b/parsons/mattermost.nix similarity index 100% rename from services/mattermost.nix rename to parsons/mattermost.nix diff --git a/services/murmur.nix b/parsons/murmur.nix similarity index 100% rename from services/murmur.nix rename to parsons/murmur.nix diff --git a/services/nextcloud.nix b/parsons/nextcloud.nix similarity index 100% rename from services/nextcloud.nix rename to parsons/nextcloud.nix diff --git a/services/nginx-pages.nix b/parsons/nginx-pages.nix similarity index 100% rename from services/nginx-pages.nix rename to parsons/nginx-pages.nix diff --git a/services/tracktrain.nix b/parsons/tracktrain.nix similarity index 100% rename from services/tracktrain.nix rename to parsons/tracktrain.nix diff --git a/services/uffd.nix b/parsons/uffd.nix similarity index 100% rename from services/uffd.nix rename to parsons/uffd.nix diff --git a/services/vaultwarden.nix b/parsons/vaultwarden.nix similarity index 100% rename from services/vaultwarden.nix rename to parsons/vaultwarden.nix diff --git a/pkgs/default.nix b/pkgs/default.nix index e45732a..3c14078 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -8,46 +8,15 @@ let newpkgs = { - mattermost = callPackage ./mattermost {inherit sources;}; + mattermost = callPackage ./mattermost.nix {inherit sources;}; tracktrain = import sources.tracktrain { nixpkgs = pkgs; compiler = "default"; }; - # a version of the lounge with some extra css that - # hides things the hacc-voc doesn't need - thelounge = pkgs.stdenv.mkDerivation { - name = "thelounge-hacked"; - src = pkgs.thelounge; - - phases = [ "buildPhase" "installPhase" ]; - buildPhase = '' - cp $src/* -r . - chmod 777 lib/node_modules/thelounge/public/css/style.css - cat ${./thelounge/css-patch.css} >> lib/node_modules/thelounge/public/css/style.css - ''; - - installPhase = '' - mkdir -p $out - cp * -r $out - ''; - meta.mainProgram = "thelounge"; - }; - uffd = oldstable.callPackage ./uffd { }; - netbox = pkgs.netbox.override (super: rec { - python3 = super.python3.override (oldpy: { - packageOverrides = self: super: { - social-auth-core = super.social-auth-core.overrideAttrs ( old: { - name = "social-auth-with-uffd"; - patches = [ ./netbox/0001-add-uffd-oauth2-backend.patch ]; - }); - }; - }); - }); - inherit (oldstable) uwsgi flask; }; diff --git a/pkgs/mattermost/default.nix b/pkgs/mattermost.nix similarity index 100% rename from pkgs/mattermost/default.nix rename to pkgs/mattermost.nix diff --git a/pkgs/netbox/0001-add-uffd-oauth2-backend.patch b/pkgs/netbox/0001-add-uffd-oauth2-backend.patch deleted file mode 100644 index 07e9507..0000000 --- a/pkgs/netbox/0001-add-uffd-oauth2-backend.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 00e282e32b46bb4b6040dc3810599c693306c0ec Mon Sep 17 00:00:00 2001 -From: David Croft -Date: Thu, 24 Mar 2022 11:09:14 +0000 -Subject: [PATCH] add uffd oauth2 backend - ---- - social_core/backends/uffd.py | 51 ++++++++++++++++++++++++++++++++++++ - 1 file changed, 51 insertions(+) - create mode 100644 social_core/backends/uffd.py - -diff --git a/social_core/backends/uffd.py b/social_core/backends/uffd.py -new file mode 100644 -index 00000000..fb8ffb62 ---- /dev/null -+++ b/social_core/backends/uffd.py -@@ -0,0 +1,51 @@ -+from urllib.parse import urlencode -+ -+from .oauth import BaseOAuth2 -+ -+ -+class UffdOAuth2(BaseOAuth2): -+ """Uffd OAuth2 authentication backend -+ -+ You need to set the following config: -+ SOCIAL_AUTH_UFFD_KEY - client id -+ SOCIAL_AUTH_UFFD_SECRET - client secret -+ SOCIAL_AUTH_UFFD_BASE_URL - base url to uffd installation -+ """ -+ -+ name = 'uffd' -+ ACCESS_TOKEN_METHOD = 'POST' -+ REFRESH_TOKEN_METHOD = 'POST' -+ SCOPE_SEPARATOR = ' ' -+ STATE_PARAMETER = True -+ REDIRECT_STATE = False -+ EXTRA_DATA = [ -+ ('id', 'id'), -+ ] -+ -+ def get_user_details(self, response): -+ """Return user details from a Uffd account""" -+ fullname, first_name, last_name = self.get_user_names(fullname=response.get('name')) -+ return { -+ 'username': response.get('nickname'), -+ 'email': response.get('email') or '', -+ 'fullname': fullname, -+ 'first_name': first_name, -+ 'last_name': last_name, -+ } -+ -+ def user_data(self, access_token, *args, **kwargs): -+ """Loads user data from service""" -+ url = self.userinfo_url() + '?' + urlencode({'access_token': access_token}) -+ try: -+ return self.get_json(url) -+ except ValueError: -+ return None -+ -+ def authorization_url(self): -+ return self.setting('BASE_URL') + '/oauth2/authorize' -+ -+ def access_token_url(self): -+ return self.setting('BASE_URL') + '/oauth2/token' -+ -+ def userinfo_url(self): -+ return self.setting('BASE_URL') + '/oauth2/userinfo' --- -2.38.1 - diff --git a/pkgs/thelounge/css-patch.css b/pkgs/thelounge/css-patch.css deleted file mode 100644 index 0d058b6..0000000 --- a/pkgs/thelounge/css-patch.css +++ /dev/null @@ -1,24 +0,0 @@ - -/* Hides extra fields on connect screen */ -.connect-row:nth-of-type(4) { - display: none !important; -} - -.connect-row:nth-of-type(2) { - display: none !important; -} - -.connect-row:nth-of-type(5) { - display: none !important; -} - - -/* Hides side panel button */ -.header > button:first-child { - display: none !important; -} - -/* Hides channel options button (includes leave option) */ -.header > button:nth-last-child(2) { - display: none !important; -} diff --git a/services/thelounge.nix b/services/thelounge.nix deleted file mode 100644 index be7b556..0000000 --- a/services/thelounge.nix +++ /dev/null @@ -1,65 +0,0 @@ -{ config, lib, pkgs, evalConfig, ... }: - -{ - containers.thelounge = { - autoStart = true; - privateNetwork = true; - hostAddress = "192.168.100.1"; - localAddress = "192.168.100.4"; - bindMounts = { - "/var/lib/thelounge" = { - hostPath = "/persist/containers/thelounge"; - isReadOnly = false; - }; - }; - - path = evalConfig ({ config, lib, ... }: { - services.thelounge = { - enable = true; - - extraConfig = { - public = true; - package = pkgs.thelounge; - - # respect X-Forwarded-For - reverseProxy = true; - defaults = { - name = "libera chat"; - host = "irc.eu.libera.chat"; - port = 6697; - # encrypt things! - tls = true; - # yes, please do actually check the cert … - rejectUnauthorized = true; - nick = "haccGuest%%%%"; - join = "#hacc-webchat"; - }; - lockNetwork = true; - - # don't log messages (default is text / sqlite) - messageStorage = []; - - # darker theme - #theme = "morning"; - - # these three should result in having link previews - # which are fetched only by the server, then proxied - # (i.e. clients won't directly connect to arbitrary - # domains to get previews) - prefetch = true; - prefetchStorage = true; - disableMediaPreview = true; - - leaveMessage = "happy haccing"; - }; - }; - }); - }; - - services.nginx.virtualHosts."webchat.voc.hacc.space" = { - locations."/".proxyPass = - "http://${config.containers.thelounge.localAddress}:9000"; - enableACME = true; - forceSSL = true; - }; -} diff --git a/websites/docs.hacc.space/Readme.md b/websites/docs.hacc.space/Readme.md new file mode 100644 index 0000000..536c2c7 --- /dev/null +++ b/websites/docs.hacc.space/Readme.md @@ -0,0 +1,44 @@ +# Markdown docs with zola. + +[Zola](https://www.getzola.org/) is a static site generated written in Rust +(which you'll notice since sometimes it panics). + +To run the site locally: + +``` +zola serve +``` + +## Directory Layout + +All the important stuff goes into `content`. If you create subdirectories, make +sure you remembered to also create an `_index.md` file for it (if in doubt, just +copy the one at `content/_index.md`); otherwise pages in there won't work. + +`templates` is *not* for site templates, but specifies how markdown files should +be turned into html. If an autogenerated link broke, you'll probably have to +change something in there. `sass` and `static` do exactly what they sound like. + +It usually shouldn't be necessary to change `config.toml`, but if it is, [here +is the list of all available options](https://www.getzola.org/documentation/getting-started/configuration/). + + +## File Layout + +Markdown files start with a frontmatter that should look something like so: + +```markdown ++++ +title = "blåhaj" +taxonomies.categories = [ "flausch" ] ++++ + +[actual markdown goes here] +``` + +The frontmatter is TOML; the `taxonomies.*` keys are special and can be used to +aggregate posts if enabled in `config.toml` (currently that's only the case for +`categories`, though). See also the [list of all available keys](https://www.getzola.org/documentation/content/page/). + +Please don't repeat the page's title in markdown, otherwise it'll appear twice +in the html. diff --git a/websites/docs.hacc.space/config.toml b/websites/docs.hacc.space/config.toml new file mode 100644 index 0000000..c890821 --- /dev/null +++ b/websites/docs.hacc.space/config.toml @@ -0,0 +1,35 @@ +# Zola's configuration file, +# +# see https://www.getzola.org/documentation/getting-started/configuration/ +# for available keys. + +# The URL the site will be built for +base_url = "https://docs.hacc.space" + +compile_sass = true +default_language = "en" + +# might be useful — this isn't a blog, obviously, but updates for new entries +# could still be nice, I guess +generate_feed = true +feed_filename = "atom.xml" + +build_search_index = true + +taxonomies = [ + { name = "categories", feed = false}, +] + +[markdown] +highlight_code = true + +[extra] # user-defined keys + +# site title text +main_title = "haccfiles documentation" + +# navbar entries +main_menu = [ + {url = "$BASE_URL", name = "Home"}, + {url = "$BASE_URL/categories", name = "Categories"} +] diff --git a/websites/docs.hacc.space/content b/websites/docs.hacc.space/content new file mode 120000 index 0000000..92a7f82 --- /dev/null +++ b/websites/docs.hacc.space/content @@ -0,0 +1 @@ +../../docs \ No newline at end of file diff --git a/websites/docs.hacc.space/default.nix b/websites/docs.hacc.space/default.nix new file mode 100644 index 0000000..c1c5453 --- /dev/null +++ b/websites/docs.hacc.space/default.nix @@ -0,0 +1,19 @@ +{ stdenvNoCC, zola, writeScriptBin }: + +stdenvNoCC.mkDerivation rec { + name = "docs.hacc.space-static"; + + src = ./.; + + phases = [ "buildPhase" ]; + buildInputs = [ zola ]; + buildPhase = '' + cd $src + mkdir -p $out + zola build --output-dir $out + ''; + + watch = writeScriptBin "watch" '' + ${zola}/bin/zola serve ${src} "$@" + ''; +} diff --git a/websites/docs.hacc.space/sass/style.scss b/websites/docs.hacc.space/sass/style.scss new file mode 100644 index 0000000..2fd384b --- /dev/null +++ b/websites/docs.hacc.space/sass/style.scss @@ -0,0 +1,168 @@ + +@font-face { + font-family: 'share-tech'; + src: url('ShareTech-Regular.ttf') format('truetype'); +} + +html { + overflow: hidden; + height: 100%; +} + +body { + background-color: #000; + color: #fff; + + overflow-y: auto; + overflow-x: hidden; + height: 100%; +} + +#content { + font-family: 'share-tech'; + margin-left: auto; + margin-right: auto; + max-width: 60em; + font-size: 16pt; + position: relative; +} + +p.subtitle { + font-size: 14pt; + font-style: normal; + color: gray; +} + +article { + margin-bottom: 4em; +} + +#searchresults { + width: 90%; + text-align: right; + right: 0; + position: absolute; + background-color: black; + top: 5em; + color: gray; +} + +#searchresults div { + padding: 0.5em; + border-top: 1px dashed gray; +} + +#searchresults div:last-child { + border-bottom: 1px dashed gray; +} + +.searchresultprevtext { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + display: inline-block; + width: 40em; + float: left; +} + +footer.content { + top: 50px; + color: #cccccc; + font-size: 14px; + margin-bottom: 4em; +} + +footer a { + color: #cccccc; +} + +.logo { + position: relative; + width: 100%; +} +.logo > img { + width: 300px; + max-width: 100%; +} + +h1 { + font-size: 32pt; +} + +#headernav { + text-align: right; + margin: 1em; +} + +#headernav > a { + padding: 0.2em; + font-size: 20pt; + font-family: share-tech; +} + +h1, h2, h3, h4, h5, h6{ + font-weight: 600; + display: inline; + font-family: share-tech; + background: rgb(59,115,185); + background: linear-gradient(90deg, rgb(59, 115, 185) 0%, rgb(229, 35, 33) 100%); + background-clip: border-box; + color: transparent; + -webkit-background-clip: text; + background-clip: text; +} +/* +h4 { + //font-weight: 600; + //display: inline; + font-family: share-tech; + //background: rgb(59,115,185); + //background: linear-gradient(90deg, rgb(59, 115, 185) 0%, rgb(229, 35, 33) 100%); + //background-clip: border-box; + color: #fff; + //-webkit-background-clip: text; + //background-clip: text; +} +*/ +a { + text-decoration: none; + color: #3b73b9; + transition: color .1s linear; +} +a:hover { + /*color: #e52321;*/ + color: #4e9af9; +} + +ul { + margin-top: 0; +} + + +pre { + padding: 1rem; + overflow: auto; + font-size: 16px; +} +// The line numbers already provide some kind of left/right padding +pre[data-linenos] { + padding: 1rem 0; +} +pre table td { + padding: 0; +} +// The line number cells +pre table td:nth-of-type(1) { + text-align: center; + user-select: none; +} +pre mark { + // If you want your highlights to take the full width. + display: block; + // The default background colour of a mark is bright yellow + background-color: rgba(254, 252, 232, 0.9); +} +pre table { + width: 100%; + border-collapse: collapse; +} diff --git a/websites/docs.hacc.space/static/ShareTech-Regular.ttf b/websites/docs.hacc.space/static/ShareTech-Regular.ttf new file mode 100644 index 0000000..787ba83 Binary files /dev/null and b/websites/docs.hacc.space/static/ShareTech-Regular.ttf differ diff --git a/websites/docs.hacc.space/static/favicon.png b/websites/docs.hacc.space/static/favicon.png new file mode 100644 index 0000000..0f66e6a Binary files /dev/null and b/websites/docs.hacc.space/static/favicon.png differ diff --git a/websites/docs.hacc.space/static/favicon_color.png b/websites/docs.hacc.space/static/favicon_color.png new file mode 100644 index 0000000..8456767 Binary files /dev/null and b/websites/docs.hacc.space/static/favicon_color.png differ diff --git a/websites/docs.hacc.space/static/search.js b/websites/docs.hacc.space/static/search.js new file mode 100644 index 0000000..183095d --- /dev/null +++ b/websites/docs.hacc.space/static/search.js @@ -0,0 +1,52 @@ + +function mkDiv (res) { + let div = document.createElement("div"); + let a = document.createElement("a"); + a.innerText = res.doc.title; + a.href = res.ref; + let text = document.createElement("span"); + text.innerText = res.doc.body.slice(0,400).replaceAll("\n", " "); + text.classList.add("searchresultprevtext"); + + div.appendChild(text); + div.appendChild(a); + return div; +} + +window.onload = () => { + console.log("hello!") + let searchbox = document.getElementById("searchbox"); + searchbox.innerHTML = + " \ + "; + + let searchinput = document.getElementById("searchinput"); + let searchresults = document.getElementById("searchresults"); + + let index = elasticlunr.Index.load(window.searchIndex); + + searchinput.addEventListener("keyup", () => { + let term = searchinput.value.trim(); + let results = []; + if (term !== "") { + results = index.search(term, {}); + console.log(results); + + while (searchresults.lastChild) { + searchresults.removeChild(searchresults.lastChild) + } + if (results.length !== 0) { + let resultdivs = results.map(mkDiv); + resultdivs.map((div) => searchresults.appendChild(div)); + } else { + searchresults.innerHTML = + term.length <= 4 ? + "
Need at least four characters to search.
" + : "
No results here.
"; + } + searchresults.style.display = "initial"; + } else { + searchresults.style.display = "none"; + } + }); +} diff --git a/websites/docs.hacc.space/templates/base.html b/websites/docs.hacc.space/templates/base.html new file mode 100644 index 0000000..2810c83 --- /dev/null +++ b/websites/docs.hacc.space/templates/base.html @@ -0,0 +1,43 @@ + + + + + {{ config.extra.main_title }} + + + + + + + {% block head_extra %} + {% endblock head_extra %} + + +
+
+

{{ config.extra.main_title }}

+ +
+ + {% block content %} {% endblock %} + + + +
+ + diff --git a/websites/docs.hacc.space/templates/blog.html b/websites/docs.hacc.space/templates/blog.html new file mode 100644 index 0000000..63775bc --- /dev/null +++ b/websites/docs.hacc.space/templates/blog.html @@ -0,0 +1,12 @@ +{% extends "base.html" %} + +{% block content %} +

+ {{ section.title }} +

+ +{% endblock content %} diff --git a/websites/docs.hacc.space/templates/categories/list.html b/websites/docs.hacc.space/templates/categories/list.html new file mode 100644 index 0000000..1394c85 --- /dev/null +++ b/websites/docs.hacc.space/templates/categories/list.html @@ -0,0 +1,17 @@ +{% extends "base.html" %} + +{% block content %} +
+ +

Categories

+

+ {% if terms %} +

    + {% for term in terms %} +
  • {{ term.name }} ({{ term.pages | length }})
  • + {% endfor %} +
+ {% endif %} +

+
+{% endblock content %} diff --git a/websites/docs.hacc.space/templates/categories/single.html b/websites/docs.hacc.space/templates/categories/single.html new file mode 100644 index 0000000..69133a4 --- /dev/null +++ b/websites/docs.hacc.space/templates/categories/single.html @@ -0,0 +1,12 @@ +{% extends "base.html" %} + +{% import "post_macros.html" as post_macros %} +{% block content %} + +

Posts in category "{{ term.name }}"

+ {% for page in term.pages %} +

+

{{ page.title }}

+

+ {% endfor %} +{% endblock content %} diff --git a/websites/docs.hacc.space/templates/doc-page.html b/websites/docs.hacc.space/templates/doc-page.html new file mode 100644 index 0000000..f433657 --- /dev/null +++ b/websites/docs.hacc.space/templates/doc-page.html @@ -0,0 +1,15 @@ +{% extends "base.html" %} + +{% import "post_macros.html" as post_macros %} +{% block content %} +
+ +
+{% endblock content %} diff --git a/websites/docs.hacc.space/templates/index.html b/websites/docs.hacc.space/templates/index.html new file mode 100644 index 0000000..8fae414 --- /dev/null +++ b/websites/docs.hacc.space/templates/index.html @@ -0,0 +1,23 @@ +{% extends "base.html" %} + +{% block content %} +
+ {% for page in section.pages %} +

+

{{ page.title }}

+

+ {% endfor %} + + {% for sub in section.subsections %} + {% set subsection = get_section(path=sub) %} +

+

{{ subsection.title }}

+ {% for page in subsection.pages %} +

+

{{ page.title }}

+

+ {% endfor %} +

+ {% endfor %} +
+{% endblock content %} diff --git a/websites/docs.hacc.space/templates/post_macros.html b/websites/docs.hacc.space/templates/post_macros.html new file mode 100644 index 0000000..1fb7e9b --- /dev/null +++ b/websites/docs.hacc.space/templates/post_macros.html @@ -0,0 +1,15 @@ +{% macro paginator_nav(paginator) %} + + + +{% endmacro paginator_nav %} diff --git a/websites/docs.hacc.space/templates/section.html b/websites/docs.hacc.space/templates/section.html new file mode 100644 index 0000000..d3a223b --- /dev/null +++ b/websites/docs.hacc.space/templates/section.html @@ -0,0 +1,15 @@ +{% extends "index.html" %} + +{% block content %} +

{{ section.title }}

+

{{ section.content | safe }}

+

Pages in section

+ + +{% endblock content %}