Compare commits
No commits in common. "12e4cba3e6489045d63d2ff384a6c7e9f1541100" and "c2022d9c60cde807b3f129b88a2f162cdc543252" have entirely different histories.
12e4cba3e6
...
c2022d9c60
57 changed files with 248 additions and 874 deletions
45
README.md
45
README.md
|
@ -1,26 +1,22 @@
|
||||||
# hacc nixfiles
|
# hacc nixfiles
|
||||||
|
|
||||||
Welcome to the hacc nixfiles (haccfiles). This is how we configure (most of)
|
welcome to hacc nixfiles (haccfiles). this is the code describing our nix-based infrastructure.
|
||||||
our infrastructure.
|
|
||||||
|
|
||||||
## General layout
|
## structure
|
||||||
|
|
||||||
- `flake.nix`: Entrypoint & dependencies
|
- `flake.nix`: Entrypoint & dependencies
|
||||||
|
- `common/`: configuration common to all hosts
|
||||||
- `modules/`: home-grown modules for hacc-specific services
|
- `modules/`: home-grown modules for hacc-specific services
|
||||||
- `pkgs/`: packages we need which aren't in nixpkgs
|
- `pkgs/`: packages we built and don't want to upstream
|
||||||
- `websites/`: static websites hosted by us
|
- `hosts/`: configuration.nix per host (currently there's only one of those)
|
||||||
- `common/`: meta-level config, reusable across machines
|
- `services/`: all services we run; imported in appropriate host config
|
||||||
- `parsons/`: our sole server, its config & the services it runs
|
- `websites/`: static websites we deploy somewhere
|
||||||
|
|
||||||
Right now, we only have a single host. We might add more again in the future.
|
## working with the haccfiles
|
||||||
|
|
||||||
## Working with this repo
|
|
||||||
|
|
||||||
You will need a flake-enabled nix installation, and have your ssh config set up
|
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`.
|
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):
|
It's recommended to use [deploy_rs](https://github.com/serokell/deploy-rs):
|
||||||
~~~shell
|
~~~shell
|
||||||
deploy .#parsons -k [--dry-activate]
|
deploy .#parsons -k [--dry-activate]
|
||||||
|
@ -32,13 +28,30 @@ nixos-rebuild --flake .#parsons --target-host parsons \
|
||||||
--use-remote-sudo --use-substitutes [test|switch|dry-activate]
|
--use-remote-sudo --use-substitutes [test|switch|dry-activate]
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
### Re-deploying on parsons itself
|
If for some reason you have `nix` but not `nixos-rebuild`, you can still build the
|
||||||
|
system closure using:
|
||||||
Simply do:
|
|
||||||
~~~shell
|
~~~shell
|
||||||
nixos-rebuild --flake .#parsons [test|switch|dry-activate]
|
nix build .#nixosConfigurations.parsons.config.system.build.toplevel
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
|
(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
|
## Working on websites
|
||||||
|
|
||||||
Websites are exposed as flake outputs: if you're working on a website & want to
|
Websites are exposed as flake outputs: if you're working on a website & want to
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
+++
|
|
||||||
title = "hacc infra documentation"
|
|
||||||
page_template = "doc-page.html"
|
|
||||||
sort_by="title"
|
|
||||||
+++
|
|
||||||
|
|
||||||
|
|
10
docs/auth.md
10
docs/auth.md
|
@ -1,10 +0,0 @@
|
||||||
+++
|
|
||||||
title = "Authentication"
|
|
||||||
categories = [ "services", "uffd" ]
|
|
||||||
+++
|
|
||||||
|
|
||||||
We use [uffd](https://git.cccv.de/uffd/uffd) for our SSO, for better or worse.
|
|
||||||
Mostly for worse.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
+++
|
|
||||||
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)
|
|
|
@ -1,16 +0,0 @@
|
||||||
+++
|
|
||||||
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
|
|
||||||
|
|
17
docs/lxc.md
17
docs/lxc.md
|
@ -1,17 +0,0 @@
|
||||||
+++
|
|
||||||
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 <name> -- /usr/bin/sudo -i`
|
|
||||||
- restarting the keycloak and ldap containers
|
|
||||||
`lxc-stop -n <name> && lxc-start -n <name>`
|
|
||||||
- restarting their network bridge:
|
|
||||||
`systemctl restart lxcbr0-netdev.services`
|
|
|
@ -1,18 +0,0 @@
|
||||||
+++
|
|
||||||
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.
|
|
|
@ -1,21 +0,0 @@
|
||||||
+++
|
|
||||||
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.
|
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
+++
|
|
||||||
title = "Services"
|
|
||||||
sort_by = "title"
|
|
||||||
page_template = "doc-page.html"
|
|
||||||
+++
|
|
|
@ -1,19 +0,0 @@
|
||||||
+++
|
|
||||||
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
|
|
|
@ -1,68 +0,0 @@
|
||||||
+++
|
|
||||||
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.
|
|
|
@ -1,65 +0,0 @@
|
||||||
+++
|
|
||||||
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!)
|
|
||||||
|
|
|
@ -1,40 +0,0 @@
|
||||||
+++
|
|
||||||
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
|
|
|
@ -1,18 +0,0 @@
|
||||||
+++
|
|
||||||
title = "$Service Name"
|
|
||||||
draft = true ## Remove this line to make file appear on website
|
|
||||||
+++
|
|
||||||
|
|
||||||
<general information & pointers to official documentation>
|
|
||||||
|
|
||||||
# Usage
|
|
||||||
<usage from an admin's perspective>
|
|
||||||
|
|
||||||
# Config Notes
|
|
||||||
<what should one keep in mind when reading the nix file?>
|
|
||||||
|
|
||||||
## Updating
|
|
||||||
<anything to keep in mind?>
|
|
||||||
|
|
||||||
# Hacks
|
|
||||||
<ugly things which might break or cause general ???? states>
|
|
|
@ -1,24 +0,0 @@
|
||||||
+++
|
|
||||||
title = "Use ZFS snapshot"
|
|
||||||
taxonomies.categories = [ "zfs", "snapshot", "filesystem", "backup", "update", "upgrade" ]
|
|
||||||
+++
|
|
||||||
|
|
||||||
## Make a ZFS snapshot
|
|
||||||
~~~shell
|
|
||||||
sudo zfs snapshot zroot/safe/persist@<name>
|
|
||||||
~~~
|
|
||||||
|
|
||||||
## Rollback
|
|
||||||
|
|
||||||
### single files
|
|
||||||
The snapshots can be accessed under `<mountpoint>/.zfs/snapshot/...`
|
|
||||||
|
|
||||||
### fully
|
|
||||||
~~~shell
|
|
||||||
sudo zfs rollback zroot/safe/persist@<name>
|
|
||||||
~~~
|
|
||||||
|
|
||||||
## Delete a ZFS snapshot
|
|
||||||
~~~shell
|
|
||||||
sudo zfs destroy zroot/safe/persist@<name>
|
|
||||||
~~~
|
|
|
@ -71,7 +71,7 @@
|
||||||
nixosConfigurations.parsons = nixpkgs.lib.nixosSystem {
|
nixosConfigurations.parsons = nixpkgs.lib.nixosSystem {
|
||||||
system = "x86_64-linux";
|
system = "x86_64-linux";
|
||||||
modules = [
|
modules = [
|
||||||
./parsons/configuration.nix
|
./hosts/parsons/configuration.nix
|
||||||
sops-nix.nixosModules.sops
|
sops-nix.nixosModules.sops
|
||||||
{ nixpkgs.pkgs = pkgs; }
|
{ nixpkgs.pkgs = pkgs; }
|
||||||
{ environment.etc."haccfiles".source = self.outPath; }
|
{ environment.etc."haccfiles".source = self.outPath; }
|
||||||
|
@ -98,10 +98,7 @@
|
||||||
deploy-rs.lib;
|
deploy-rs.lib;
|
||||||
|
|
||||||
packages.x86_64-linux =
|
packages.x86_64-linux =
|
||||||
let
|
self.nixosConfigurations.parsons.config.hacc.websites.builders;
|
||||||
websites = self.nixosConfigurations.parsons.config.hacc.websites.builders;
|
|
||||||
in
|
|
||||||
{ docs = websites."docs.hacc.space"; } // websites;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,27 +2,34 @@
|
||||||
|
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
../common
|
../../common
|
||||||
./hardware.nix
|
./hardware.nix
|
||||||
modules.encboot
|
modules.encboot
|
||||||
modules.network.nftables
|
modules.network.nftables
|
||||||
modules.nftnat
|
modules.nftnat
|
||||||
sources.nix-hexchen.nixosModules.profiles.nopersist
|
sources.nix-hexchen.nixosModules.profiles.nopersist
|
||||||
./nextcloud.nix
|
|
||||||
./mattermost.nix
|
../../services/nextcloud.nix
|
||||||
./murmur.nix
|
../../services/mattermost.nix
|
||||||
./hedgedoc-hacc.nix
|
../../services/thelounge.nix
|
||||||
./hedgedoc-i4f.nix
|
../../services/murmur.nix
|
||||||
./mail.nix
|
../../services/hedgedoc-hacc.nix
|
||||||
./gitea.nix
|
../../services/hedgedoc-i4f.nix
|
||||||
./nginx-pages.nix
|
../../services/mail.nix
|
||||||
./vaultwarden.nix
|
../../services/gitea.nix
|
||||||
./tracktrain.nix
|
../../services/nginx-pages.nix
|
||||||
./uffd.nix
|
../../services/vaultwarden.nix
|
||||||
|
../../services/tracktrain.nix
|
||||||
|
../../services/uffd.nix
|
||||||
|
|
||||||
./lxc.nix
|
./lxc.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
hexchen.bindmounts."/var/lib/acme" = "/persist/var/lib/acme";
|
hexchen.bindmounts."/var/lib/acme" = "/persist/var/lib/acme";
|
||||||
|
# fileSystems."/var/lib/acme" = {
|
||||||
|
# device = "/persist/var/lib/acme";
|
||||||
|
# fsType = "bind";
|
||||||
|
# };
|
||||||
|
|
||||||
hexchen.encboot = {
|
hexchen.encboot = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
@ -30,7 +37,7 @@
|
||||||
networkDrivers = [ "igb" ];
|
networkDrivers = [ "igb" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
sops.defaultSopsFile = ../secrets.yaml;
|
sops.defaultSopsFile = ../../secrets.yaml;
|
||||||
sops.age.sshKeyPaths = [ "/persist/ssh/ssh_host_ed25519_key" ];
|
sops.age.sshKeyPaths = [ "/persist/ssh/ssh_host_ed25519_key" ];
|
||||||
|
|
||||||
boot.loader.grub.enable = true;
|
boot.loader.grub.enable = true;
|
|
@ -8,15 +8,46 @@ let
|
||||||
|
|
||||||
newpkgs = {
|
newpkgs = {
|
||||||
|
|
||||||
mattermost = callPackage ./mattermost.nix {inherit sources;};
|
mattermost = callPackage ./mattermost {inherit sources;};
|
||||||
|
|
||||||
tracktrain = import sources.tracktrain {
|
tracktrain = import sources.tracktrain {
|
||||||
nixpkgs = pkgs;
|
nixpkgs = pkgs;
|
||||||
compiler = "default";
|
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 { };
|
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;
|
inherit (oldstable) uwsgi flask;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
70
pkgs/netbox/0001-add-uffd-oauth2-backend.patch
Normal file
70
pkgs/netbox/0001-add-uffd-oauth2-backend.patch
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
From 00e282e32b46bb4b6040dc3810599c693306c0ec Mon Sep 17 00:00:00 2001
|
||||||
|
From: David Croft <david@sargasso.net>
|
||||||
|
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
|
||||||
|
|
24
pkgs/thelounge/css-patch.css
Normal file
24
pkgs/thelounge/css-patch.css
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
|
@ -4,7 +4,7 @@
|
||||||
{
|
{
|
||||||
hacc.websites = {
|
hacc.websites = {
|
||||||
enable = true;
|
enable = true;
|
||||||
directory = "${../.}/websites";
|
directory = ../websites;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
65
services/thelounge.nix
Normal file
65
services/thelounge.nix
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
{ 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;
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,44 +0,0 @@
|
||||||
# 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.
|
|
|
@ -1,35 +0,0 @@
|
||||||
# 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"}
|
|
||||||
]
|
|
|
@ -1 +0,0 @@
|
||||||
../../docs
|
|
|
@ -1,28 +0,0 @@
|
||||||
{ stdenvNoCC, zola, writeScriptBin }:
|
|
||||||
|
|
||||||
stdenvNoCC.mkDerivation rec {
|
|
||||||
name = "docs.hacc.space-static";
|
|
||||||
|
|
||||||
# HINT: this is cursed. Nix flakes have no optimisation to deal with ${./.},
|
|
||||||
# so we wind up having to do this to make the symlink to content/ work.
|
|
||||||
# (we still need to manually adjust it — but at least this way we can find
|
|
||||||
# its target without further hoops)
|
|
||||||
#
|
|
||||||
# This does also mean we now copy the entire flake into the Nix store twice.
|
|
||||||
# Yay for flakes!
|
|
||||||
src = "${../../.}/websites/docs.hacc.space";
|
|
||||||
|
|
||||||
phases = [ "buildPhase" ];
|
|
||||||
buildInputs = [ zola ];
|
|
||||||
buildPhase = ''
|
|
||||||
cp -r $src/* .
|
|
||||||
rm content
|
|
||||||
ln -s $src/../../docs content
|
|
||||||
zola build --output-dir $out
|
|
||||||
'';
|
|
||||||
|
|
||||||
watch = writeScriptBin "watch" ''
|
|
||||||
cd $(git rev-parse --show-toplevel)/websites/docs.hacc.space
|
|
||||||
${zola}/bin/zola serve --output-dir /tmp/hacc-docs "$@"
|
|
||||||
'';
|
|
||||||
}
|
|
|
@ -1,168 +0,0 @@
|
||||||
|
|
||||||
@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;
|
|
||||||
}
|
|
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 3.7 KiB |
Binary file not shown.
Before Width: | Height: | Size: 5.2 KiB |
|
@ -1,52 +0,0 @@
|
||||||
|
|
||||||
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 =
|
|
||||||
"<input id='searchinput' placeholder='search ...'></input> \
|
|
||||||
<div id='searchresults' style='display:none'></div>";
|
|
||||||
|
|
||||||
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 ?
|
|
||||||
"<div>Need at least four characters to search.</div>"
|
|
||||||
: "<div>No results here.</div>";
|
|
||||||
}
|
|
||||||
searchresults.style.display = "initial";
|
|
||||||
} else {
|
|
||||||
searchresults.style.display = "none";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>{{ config.extra.main_title }}</title>
|
|
||||||
<link rel="icon" type="image/png" href="favicon.png">
|
|
||||||
<link rel="alternate" type="application/atom+xml" title="Feed" href="{{ get_url(path="atom.xml", trailing_slash=false) }}">
|
|
||||||
<link rel="stylesheet" href="{{ get_url(path="style.css", trailing_slash=false) | safe }}">
|
|
||||||
<script src="{{ get_url(path="search_index.en.js", trailing_slash=false) | safe }}"></script>
|
|
||||||
<script src="{{ get_url(path="elasticlunr.min.js", trailing_slash=false) | safe }}"></script>
|
|
||||||
<script src="{{ get_url(path="search.js", trailing_slash=false) | safe }}"></script>
|
|
||||||
{% block head_extra %}
|
|
||||||
{% endblock head_extra %}
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="content">
|
|
||||||
<header style="height:10em">
|
|
||||||
<a href="{{config.base_url}}"><h2 style="float:left">{{ config.extra.main_title }}</h2></a>
|
|
||||||
<nav id="headernav" style="float:right">
|
|
||||||
{% for item in config.extra.main_menu %}
|
|
||||||
<a itemprop="url"
|
|
||||||
class="{% if item.url | replace(from="$BASE_URL", to=config.base_url) == current_url %}active{% endif %}"
|
|
||||||
href="{{ item.url | safe | replace(from="$BASE_URL", to=config.base_url) }}">
|
|
||||||
{{ item.name }}
|
|
||||||
</a>
|
|
||||||
{% endfor %}
|
|
||||||
<div id="searchbox">
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
{% block content %} {% endblock %}
|
|
||||||
|
|
||||||
<footer class="content" style="z-index: 200">
|
|
||||||
<div>
|
|
||||||
<a href="https://git.infra4future.de/hacc/haccfiles">Source in git</a> •
|
|
||||||
<a href="https://infra4future.de/impressum.html">Imprint</a>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,12 +0,0 @@
|
||||||
{% extends "base.html" %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<h1 class="title">
|
|
||||||
{{ section.title }}
|
|
||||||
</h1>
|
|
||||||
<ul>
|
|
||||||
{% for page in section.pages %}
|
|
||||||
<li><a href="{{ page.permalink | safe }}">{{ page.title }}</a></li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
{% endblock content %}
|
|
|
@ -1,17 +0,0 @@
|
||||||
{% extends "base.html" %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<main>
|
|
||||||
|
|
||||||
<h1>Categories</h1>
|
|
||||||
<p>
|
|
||||||
{% if terms %}
|
|
||||||
<ul>
|
|
||||||
{% for term in terms %}
|
|
||||||
<li><a href="{{ term.permalink | safe }}">{{ term.name }}</a> ({{ term.pages | length }})</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
{% endif %}
|
|
||||||
</p>
|
|
||||||
</main>
|
|
||||||
{% endblock content %}
|
|
|
@ -1,12 +0,0 @@
|
||||||
{% extends "base.html" %}
|
|
||||||
|
|
||||||
{% import "post_macros.html" as post_macros %}
|
|
||||||
{% block content %}
|
|
||||||
|
|
||||||
<h1>Posts in category "{{ term.name }}"</h1>
|
|
||||||
{% for page in term.pages %}
|
|
||||||
<p>
|
|
||||||
<h2><a href="{{ page.permalink | safe }}">{{ page.title }}</a></h2>
|
|
||||||
</p>
|
|
||||||
{% endfor %}
|
|
||||||
{% endblock content %}
|
|
|
@ -1,15 +0,0 @@
|
||||||
{% extends "base.html" %}
|
|
||||||
|
|
||||||
{% import "post_macros.html" as post_macros %}
|
|
||||||
{% block content %}
|
|
||||||
<main>
|
|
||||||
<article itemscope itemtype="http://schema.org/CreativeWork">
|
|
||||||
<header>
|
|
||||||
<h1><a href="{{ page.permalink | safe }}">
|
|
||||||
{{ page.title }}
|
|
||||||
</a></h1>
|
|
||||||
</header>
|
|
||||||
{{ page.content | safe }}
|
|
||||||
</article>
|
|
||||||
</main>
|
|
||||||
{% endblock content %}
|
|
|
@ -1,23 +0,0 @@
|
||||||
{% extends "base.html" %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<main>
|
|
||||||
{% for page in section.pages %}
|
|
||||||
<p>
|
|
||||||
<h3><a href="{{ page.permalink | safe }}">{{ page.title }}</a></h3>
|
|
||||||
</p>
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
{% for sub in section.subsections %}
|
|
||||||
{% set subsection = get_section(path=sub) %}
|
|
||||||
<p>
|
|
||||||
<h2><a href="{{ subsection.permalink | safe }}">{{ subsection.title }}</a></h2>
|
|
||||||
{% for page in subsection.pages %}
|
|
||||||
<p>
|
|
||||||
<h3 style="margin-left:1em"><a href="{{ page.permalink | safe }}">{{ page.title }}</a></h3>
|
|
||||||
</p>
|
|
||||||
{% endfor %}
|
|
||||||
</p>
|
|
||||||
{% endfor %}
|
|
||||||
</main>
|
|
||||||
{% endblock content %}
|
|
|
@ -1,15 +0,0 @@
|
||||||
{% macro paginator_nav(paginator) %}
|
|
||||||
|
|
||||||
<nav>
|
|
||||||
<p>
|
|
||||||
{% if paginator.previous %}
|
|
||||||
<a href="{{ paginator.previous }}">« Previous</a> |
|
|
||||||
{% endif %}
|
|
||||||
<span>Page {{ paginator.current_index }} of {{ paginator.number_pagers }}</span>
|
|
||||||
{% if paginator.next %}
|
|
||||||
| <a href="{{ paginator.next }}">Next »</a>
|
|
||||||
{% endif %}
|
|
||||||
</p>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
{% endmacro paginator_nav %}
|
|
|
@ -1,15 +0,0 @@
|
||||||
{% extends "index.html" %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<h1>{{ section.title }}</h1>
|
|
||||||
<p>{{ section.content | safe }}</p>
|
|
||||||
<p>Pages in section</p>
|
|
||||||
<ul>
|
|
||||||
{% for page in section.pages | reverse %}
|
|
||||||
<li>
|
|
||||||
<em> <a href="{{ page.permalink }}"> {{ page.title }} </a> </em>
|
|
||||||
</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
{% endblock content %}
|
|
|
@ -14,7 +14,6 @@ stdenvNoCC.mkDerivation rec {
|
||||||
'';
|
'';
|
||||||
|
|
||||||
watch = writeScriptBin "watch" ''
|
watch = writeScriptBin "watch" ''
|
||||||
cd $(git rev-parse --show-toplevel)/websites/hacc.earth
|
${sfz}/bin/sfz -r ${src} "$@"
|
||||||
${sfz}/bin/sfz "$@"
|
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,6 @@ stdenvNoCC.mkDerivation rec {
|
||||||
'';
|
'';
|
||||||
|
|
||||||
watch = writeScriptBin "watch" ''
|
watch = writeScriptBin "watch" ''
|
||||||
cd $(git rev-parse --show-toplevel)/websites/help.studentsforfuture.info
|
${sfz}/bin/sfz -r ${src}
|
||||||
${sfz}/bin/sfz "$@"
|
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,8 +12,7 @@ stdenvNoCC.mkDerivation rec {
|
||||||
'';
|
'';
|
||||||
|
|
||||||
watch = writeScriptBin "watch" ''
|
watch = writeScriptBin "watch" ''
|
||||||
cd $(git rev-parse --show-toplevel)/websites/infra4future.de
|
|
||||||
rm -rf /tmp/hacc-website
|
rm -rf /tmp/hacc-website
|
||||||
${jekyll}/bin/jekyll serve --disable-disk-cache -d /tmp/hacc-website "$@"
|
${jekyll}/bin/jekyll serve -s ${src} --disable-disk-cache -d /tmp/hacc-website
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,6 @@ stdenvNoCC.mkDerivation rec {
|
||||||
'';
|
'';
|
||||||
|
|
||||||
watch = writeScriptBin "watch" ''
|
watch = writeScriptBin "watch" ''
|
||||||
cd $(git rev-parse --show-toplevel)/websites/muc.hacc.earth
|
${sfz}/bin/sfz -r ${src}
|
||||||
${sfz}/bin/sfz "$@"
|
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,8 +12,7 @@ stdenvNoCC.mkDerivation rec {
|
||||||
'';
|
'';
|
||||||
|
|
||||||
watch = writeScriptBin "watch" ''
|
watch = writeScriptBin "watch" ''
|
||||||
cd $(git rev-parse --show-toplevel)/websites/mumble.infra4future.de
|
|
||||||
rm -rf /tmp/hacc-website
|
rm -rf /tmp/hacc-website
|
||||||
${jekyll}/bin/jekyll serve --disable-disk-cache -d /tmp/hacc-website "$@"
|
${jekyll}/bin/jekyll serve -s ${src} --disable-disk-cache -d /tmp/hacc-website
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue