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 ?
+ "