Compare commits
2 commits
main
...
onlyoffice
Author | SHA1 | Date | |
---|---|---|---|
eef20d52d5 | |||
2971d1bbc0 |
82 changed files with 1613 additions and 2022 deletions
|
@ -1 +0,0 @@
|
||||||
websites/*
|
|
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
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
imports = [
|
imports = [
|
||||||
../modules
|
../modules
|
||||||
./users.nix
|
./users.nix
|
||||||
|
modules.network.nftables
|
||||||
];
|
];
|
||||||
|
|
||||||
boot.kernelPackages = lib.mkDefault pkgs.linuxPackages;
|
boot.kernelPackages = lib.mkDefault pkgs.linuxPackages;
|
||||||
|
@ -15,7 +16,6 @@
|
||||||
SystemMaxUse=512M
|
SystemMaxUse=512M
|
||||||
MaxRetentionSec=48h
|
MaxRetentionSec=48h
|
||||||
'';
|
'';
|
||||||
nix.package = pkgs.lix;
|
|
||||||
nix.gc.automatic = lib.mkDefault true;
|
nix.gc.automatic = lib.mkDefault true;
|
||||||
nix.gc.options = lib.mkDefault "--delete-older-than 7d";
|
nix.gc.options = lib.mkDefault "--delete-older-than 7d";
|
||||||
nix.settings.trusted-users = [ "root" "@wheel" ];
|
nix.settings.trusted-users = [ "root" "@wheel" ];
|
||||||
|
@ -61,7 +61,7 @@
|
||||||
whois
|
whois
|
||||||
iperf
|
iperf
|
||||||
fd
|
fd
|
||||||
eza
|
exa
|
||||||
socat
|
socat
|
||||||
tmux
|
tmux
|
||||||
gnupg
|
gnupg
|
||||||
|
@ -75,8 +75,6 @@
|
||||||
ffmpeg-full
|
ffmpeg-full
|
||||||
bat
|
bat
|
||||||
niv
|
niv
|
||||||
sqlite-interactive
|
|
||||||
hacc-scripts
|
|
||||||
];
|
];
|
||||||
|
|
||||||
security.acme.defaults.email = "info+acme@hacc.space";
|
security.acme.defaults.email = "info+acme@hacc.space";
|
||||||
|
|
|
@ -19,6 +19,18 @@
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
stuebinm = {
|
||||||
|
uid = 1005;
|
||||||
|
isNormalUser = true;
|
||||||
|
extraGroups = [ "wheel" ];
|
||||||
|
shell = pkgs.fish;
|
||||||
|
openssh.authorizedKeys.keys = [
|
||||||
|
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG7J3peZGB4XGJKI1dV5PdpQS+TzmoJ7qL//ipCG7G5K stuebinm@surltesh-echer"
|
||||||
|
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKPB74xA2GBXnDwPEEaxWLONdQyBwjDoJHYagKRQXwO2 stuebinm@abbenay"
|
||||||
|
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH8e9WrHsknoFwBm/YaigOSz9VI8dXRRR5G9BX4kKt9/ stuebinm@ilex"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
octycs = {
|
octycs = {
|
||||||
uid = 1002;
|
uid = 1002;
|
||||||
isNormalUser = true;
|
isNormalUser = true;
|
||||||
|
@ -50,37 +62,5 @@
|
||||||
];
|
];
|
||||||
hashedPassword = "$6$zkAsaVdmIduqZxez$GY9aBlYeP41F0it/VbbZzLLLRQhHAbDdFsa3e/1GS9McTuSimMHODg6HqNVEH1zSqD3afhK/0UHfqbtF5qpi90";
|
hashedPassword = "$6$zkAsaVdmIduqZxez$GY9aBlYeP41F0it/VbbZzLLLRQhHAbDdFsa3e/1GS9McTuSimMHODg6HqNVEH1zSqD3afhK/0UHfqbtF5qpi90";
|
||||||
};
|
};
|
||||||
|
|
||||||
stuebinm = {
|
|
||||||
uid = 1005;
|
|
||||||
isNormalUser = true;
|
|
||||||
extraGroups = [ "wheel" ];
|
|
||||||
shell = pkgs.fish;
|
|
||||||
openssh.authorizedKeys.keys = [
|
|
||||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG7J3peZGB4XGJKI1dV5PdpQS+TzmoJ7qL//ipCG7G5K stuebinm@surltesh-echer"
|
|
||||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKPB74xA2GBXnDwPEEaxWLONdQyBwjDoJHYagKRQXwO2 stuebinm@abbenay"
|
|
||||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH8e9WrHsknoFwBm/YaigOSz9VI8dXRRR5G9BX4kKt9/ stuebinm@ilex"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
leah2 = {
|
|
||||||
uid = 1006;
|
|
||||||
shell = pkgs.fish;
|
|
||||||
isNormalUser = true;
|
|
||||||
extraGroups = [ "wheel" "cdrom" ];
|
|
||||||
openssh.authorizedKeys.keys = [
|
|
||||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK4o/ncaQUorp/BeZesPnVhzvfoqLJW3WZHtz+CWQvFU"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
floppy = {
|
|
||||||
uid = 1007;
|
|
||||||
shell = pkgs.fish;
|
|
||||||
isNormalUser = true;
|
|
||||||
extraGroups = [ "wheel" "cdrom" ];
|
|
||||||
openssh.authorizedKeys.keys = [
|
|
||||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDyVQhFDcoMnoYivQu1h8NCTWa+2WriZ1m5BilkuUk4u"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
|
||||||
~~~
|
|
881
flake.lock
881
flake.lock
File diff suppressed because it is too large
Load diff
79
flake.nix
79
flake.nix
|
@ -2,59 +2,82 @@
|
||||||
description = "hacc infra stuff";
|
description = "hacc infra stuff";
|
||||||
|
|
||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = "nixpkgs/nixos-24.05-small";
|
mattermost-webapp.url = "https://releases.mattermost.com/8.1.3/mattermost-8.1.3-linux-amd64.tar.gz";
|
||||||
nixpkgs-unstable.url = "nixpkgs/nixos-unstable-small";
|
mattermost-webapp.flake = false;
|
||||||
nixpkgs-oldstable.url = "github:/NixOS/nixpkgs?rev=c4aec3c021620d98861639946123214207e98344";
|
mattermost-server.url = "github:mattermost/mattermost-server?ref=v8.1.3";
|
||||||
|
mattermost-server.flake = false;
|
||||||
|
|
||||||
nixos-mailserver.url = "gitlab:simple-nixos-mailserver/nixos-mailserver/nixos-24.05";
|
nixpkgs.url = "nixpkgs/nixos-23.05";
|
||||||
|
nixpkgs-oldstable.url = "github:/NixOS/nixpkgs?rev=c4aec3c021620d98861639946123214207e98344";
|
||||||
|
nix-hexchen.url = "gitlab:hexchen/nixfiles";
|
||||||
|
nixos-mailserver.url = "gitlab:simple-nixos-mailserver/nixos-mailserver/nixos-23.05";
|
||||||
tracktrain.url = "git+https://stuebinm.eu/git/tracktrain?ref=main";
|
tracktrain.url = "git+https://stuebinm.eu/git/tracktrain?ref=main";
|
||||||
tracktrain.flake = false;
|
tracktrain.flake = false;
|
||||||
|
|
||||||
deploy-rs.url = "github:serokell/deploy-rs";
|
deploy-rs.url = "github:serokell/deploy-rs";
|
||||||
deploy-rs.inputs.nixpkgs.follows = "nixpkgs";
|
deploy-rs.inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
deploy-rs.inputs.flake-compat.follows = "nix-hexchen/apple-silicon/flake-compat";
|
||||||
sops-nix.url = "github:Mic92/sops-nix";
|
sops-nix.url = "github:Mic92/sops-nix";
|
||||||
sops-nix.inputs.nixpkgs-stable.follows = "nixpkgs";
|
sops-nix.inputs.nixpkgs-stable.follows = "nixpkgs";
|
||||||
sops-nix.inputs.nixpkgs.follows = "nixpkgs-unstable";
|
|
||||||
|
|
||||||
# these exist mostly to make the flake.lock somewhat more human-friendly
|
# these exist mostly to make the flake.lock somewhat more human-friendly
|
||||||
# note that in theory doing this might break things, but it seems fairly unlikely
|
# note that in theory doing this might break things, but it seems fairly unlikely
|
||||||
|
nix-hexchen.inputs = {
|
||||||
|
nixos-mailserver.follows = "nixos-mailserver";
|
||||||
|
deploy-rs.follows = "deploy-rs";
|
||||||
|
doom-emacs.follows = "nix-hexchen/nix-doom-emacs/doom-emacs";
|
||||||
|
emacs-overlay.follows = "nix-hexchen/nix-doom-emacs/emacs-overlay";
|
||||||
|
flake-utils.follows = "/deploy-rs/utils";
|
||||||
|
flake-compat.follows = "nix-hexchen/apple-silicon/flake-compat";
|
||||||
|
sops-nix.follows = "sops-nix";
|
||||||
|
};
|
||||||
nixos-mailserver.inputs = {
|
nixos-mailserver.inputs = {
|
||||||
"nixpkgs-24_05".follows = "nixpkgs";
|
"nixpkgs-23_05".follows = "nixpkgs";
|
||||||
nixpkgs.follows = "nixpkgs-unstable";
|
|
||||||
utils.follows = "/deploy-rs/utils";
|
utils.follows = "/deploy-rs/utils";
|
||||||
flake-compat.follows = "/deploy-rs/flake-compat";
|
flake-compat.follows = "/deploy-rs/flake-compat";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = { self, nixpkgs, deploy-rs, sops-nix, ... }@inputs:
|
outputs = { self, nixpkgs, nix-hexchen, deploy-rs, sops-nix, ... }@inputs:
|
||||||
let modules = {
|
let modules = nix-hexchen.nixosModules;
|
||||||
bindMounts = import ./modules/bindmounts.nix;
|
profiles = nix-hexchen.nixosModules.profiles // {
|
||||||
nopersist = import ./modules/nopersist.nix;
|
|
||||||
encboot = import ./modules/encboot.nix;
|
|
||||||
};
|
|
||||||
profiles = {
|
|
||||||
container = import ./modules/container-profile.nix;
|
container = import ./modules/container-profile.nix;
|
||||||
};
|
};
|
||||||
pkgs = import ./pkgs {
|
pkgs = import ./pkgs {
|
||||||
sources = inputs;
|
sources = inputs;
|
||||||
system = "x86_64-linux";
|
system = "x86_64-linux";
|
||||||
config.allowUnfree = true;
|
config.allowUnfree = true;
|
||||||
config.permittedInsecurePackages = [ "nextcloud-27.1.11" ];
|
|
||||||
};
|
};
|
||||||
|
evalConfig = config: (nixpkgs.lib.nixosSystem {
|
||||||
|
system = "x86_64-linux";
|
||||||
|
modules = [
|
||||||
|
config
|
||||||
|
nix-hexchen.nixosModules.network.nftables
|
||||||
|
{
|
||||||
|
nixpkgs.pkgs = pkgs.lib.mkForce pkgs;
|
||||||
|
imports = [ profiles.container profiles.nopersist ];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
specialArgs = {
|
||||||
|
# modules still needed because a profile in nix-hexchen uses it
|
||||||
|
inherit modules evalConfig;
|
||||||
|
sources = inputs;
|
||||||
|
};
|
||||||
|
}).config.system.build.toplevel;
|
||||||
in {
|
in {
|
||||||
|
# do this by hand instead of via nix-hexchen/lib/hosts.nix, since that one
|
||||||
|
# apparently can't support pkgs depending on flake inputs
|
||||||
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
|
||||||
./modules/buildinfo.nix
|
|
||||||
./modules/containers.nix
|
|
||||||
sops-nix.nixosModules.sops
|
sops-nix.nixosModules.sops
|
||||||
{ nixpkgs.pkgs = pkgs; }
|
{ nixpkgs.pkgs = pkgs; }
|
||||||
|
{ environment.etc."haccfiles".source = self.outPath; }
|
||||||
];
|
];
|
||||||
specialArgs = {
|
specialArgs = {
|
||||||
sources = inputs;
|
sources = inputs;
|
||||||
inherit modules profiles;
|
inherit modules evalConfig;
|
||||||
inherit (nixpkgs.lib) nixosSystem;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -73,20 +96,8 @@
|
||||||
(system: deployLib: deployLib.deployChecks self.deploy)
|
(system: deployLib: deployLib.deployChecks self.deploy)
|
||||||
deploy-rs.lib;
|
deploy-rs.lib;
|
||||||
|
|
||||||
apps.x86_64-linux =
|
packages.x86_64-linux =
|
||||||
let
|
pkgs; # self.nixosConfigurations.parsons.config.hacc.websites.builders;
|
||||||
mkApp = pkg: {
|
|
||||||
type = "app";
|
|
||||||
program = pkgs.lib.getExe pkg;
|
|
||||||
};
|
|
||||||
websites = pkgs.lib.mapAttrs (name: mkApp)
|
|
||||||
self.nixosConfigurations.parsons.config.hacc.websites.builders;
|
|
||||||
in
|
|
||||||
{ docs = websites."docs.hacc.space"; } // websites;
|
|
||||||
|
|
||||||
packages.x86_64-linux = {
|
|
||||||
inherit (pkgs) mattermost hacc-scripts;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,35 +2,43 @@
|
||||||
|
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
../common
|
../../common
|
||||||
./hardware.nix
|
./hardware.nix
|
||||||
modules.encboot
|
modules.encboot
|
||||||
modules.nopersist
|
modules.network.nftables
|
||||||
./nftables.nix
|
modules.nftnat
|
||||||
./nextcloud.nix
|
sources.nix-hexchen.nixosModules.profiles.nopersist
|
||||||
./mattermost.nix
|
|
||||||
./murmur.nix
|
../../services/nextcloud.nix
|
||||||
./hedgedoc-hacc.nix
|
../../services/mattermost.nix
|
||||||
./hedgedoc-i4f.nix
|
../../services/thelounge.nix
|
||||||
./mail.nix
|
../../services/murmur.nix
|
||||||
./forgejo.nix
|
../../services/hedgedoc-hacc.nix
|
||||||
./nginx-pages.nix
|
../../services/hedgedoc-i4f.nix
|
||||||
./vaultwarden.nix
|
../../services/mail.nix
|
||||||
./tracktrain.nix
|
../../services/gitea.nix
|
||||||
./uffd.nix
|
../../services/nginx-pages.nix
|
||||||
|
../../services/vaultwarden.nix
|
||||||
|
../../services/tracktrain.nix
|
||||||
|
../../services/onlyoffice.nix
|
||||||
|
../../services/uffd.nix
|
||||||
|
|
||||||
./lxc.nix
|
./lxc.nix
|
||||||
./monit.nix
|
|
||||||
];
|
];
|
||||||
|
|
||||||
hacc.bindToPersist = [ "/var/lib/acme" ];
|
hexchen.bindmounts."/var/lib/acme" = "/persist/var/lib/acme";
|
||||||
|
# fileSystems."/var/lib/acme" = {
|
||||||
|
# device = "/persist/var/lib/acme";
|
||||||
|
# fsType = "bind";
|
||||||
|
# };
|
||||||
|
|
||||||
hacc.encboot = {
|
hexchen.encboot = {
|
||||||
enable = true;
|
enable = true;
|
||||||
dataset = "-a";
|
dataset = "-a";
|
||||||
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;
|
||||||
|
@ -40,6 +48,9 @@
|
||||||
networking.hostId = "b2867696";
|
networking.hostId = "b2867696";
|
||||||
networking.useDHCP = true;
|
networking.useDHCP = true;
|
||||||
networking.nftables.enable = true;
|
networking.nftables.enable = true;
|
||||||
|
hexchen.nftables.nat.enable = true;
|
||||||
|
networking.nat.internalInterfaces = ["ve-+"];
|
||||||
|
networking.nat.externalInterface = "enp35s0";
|
||||||
|
|
||||||
networking.hostName = "parsons";
|
networking.hostName = "parsons";
|
||||||
|
|
||||||
|
@ -51,6 +62,13 @@
|
||||||
address = "fe80::1";
|
address = "fe80::1";
|
||||||
interface = "enp35s0";
|
interface = "enp35s0";
|
||||||
};
|
};
|
||||||
|
boot = {
|
||||||
|
kernelModules = [ "nf_nat_ftp" ];
|
||||||
|
kernel.sysctl = {
|
||||||
|
"net.ipv4.conf.all.forwarding" = lib.mkOverride 90 true;
|
||||||
|
"net.ipv4.conf.default.forwarding" = lib.mkOverride 90 true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
services.nginx = {
|
services.nginx = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
@ -70,8 +88,8 @@
|
||||||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||||
|
|
||||||
services.restic.backups.tardis = {
|
services.restic.backups.tardis = {
|
||||||
passwordFile = "/run/secrets/restic/system";
|
passwordFile = "/persist/restic/system";
|
||||||
environmentFile = "/run/secrets/restic/s3creds.env";
|
environmentFile = "/persist/restic/system.s3creds";
|
||||||
paths = [
|
paths = [
|
||||||
"/home"
|
"/home"
|
||||||
"/persist"
|
"/persist"
|
||||||
|
@ -84,10 +102,5 @@
|
||||||
repository = "b2:tardis-parsons:system";
|
repository = "b2:tardis-parsons:system";
|
||||||
};
|
};
|
||||||
|
|
||||||
sops.secrets = {
|
|
||||||
"restic/system" = {};
|
|
||||||
"restic/s3creds.env" = {};
|
|
||||||
};
|
|
||||||
|
|
||||||
system.stateVersion = "21.05";
|
system.stateVersion = "21.05";
|
||||||
}
|
}
|
|
@ -28,7 +28,6 @@
|
||||||
fileSystems."/persist" =
|
fileSystems."/persist" =
|
||||||
{ device = "zroot/safe/persist";
|
{ device = "zroot/safe/persist";
|
||||||
fsType = "zfs";
|
fsType = "zfs";
|
||||||
neededForBoot = true;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
fileSystems."/home" =
|
fileSystems."/home" =
|
||||||
|
@ -56,6 +55,11 @@
|
||||||
fsType = "zfs";
|
fsType = "zfs";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
fileSystems."/var/lib/docker" =
|
||||||
|
{ device = "zroot/local/docker";
|
||||||
|
fsType = "zfs";
|
||||||
|
};
|
||||||
|
|
||||||
swapDevices = [ ];
|
swapDevices = [ ];
|
||||||
|
|
||||||
}
|
}
|
|
@ -8,6 +8,7 @@
|
||||||
prefixLength = 24;
|
prefixLength = 24;
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
networking.nat.internalInterfaces = [ "lxcbr0" ];
|
||||||
|
|
||||||
virtualisation.lxc.enable = true;
|
virtualisation.lxc.enable = true;
|
||||||
virtualisation.lxc.systemConfig = ''
|
virtualisation.lxc.systemConfig = ''
|
|
@ -1,28 +0,0 @@
|
||||||
{ config, lib, pkgs, ... }:
|
|
||||||
|
|
||||||
with lib;
|
|
||||||
|
|
||||||
let cfg = config.hacc;
|
|
||||||
|
|
||||||
in {
|
|
||||||
|
|
||||||
options.hacc.bindMounts = mkOption {
|
|
||||||
type = types.attrsOf types.str;
|
|
||||||
default = { };
|
|
||||||
example = { "/etc/asdf" = "/persist/asdf"; };
|
|
||||||
};
|
|
||||||
options.hacc.bindToPersist = mkOption {
|
|
||||||
type = types.listOf types.str;
|
|
||||||
default = [];
|
|
||||||
example = [ "postgres" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
config.fileSystems = mapAttrs (_: device: {
|
|
||||||
inherit device;
|
|
||||||
options = [ "bind" ];
|
|
||||||
}) cfg.bindMounts;
|
|
||||||
|
|
||||||
config.hacc.bindMounts = listToAttrs
|
|
||||||
(map (name: { inherit name; value = "/persist${name}"; })
|
|
||||||
cfg.bindToPersist);
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
{ config, lib, pkgs, sources, ... }:
|
|
||||||
|
|
||||||
let
|
|
||||||
self = sources.self;
|
|
||||||
|
|
||||||
formatDate = date: with lib.strings;
|
|
||||||
let
|
|
||||||
year = substring 0 4 date;
|
|
||||||
month = substring 4 2 date;
|
|
||||||
day = substring 6 2 date;
|
|
||||||
hour = substring 8 2 date;
|
|
||||||
minute = substring 10 2 date;
|
|
||||||
second = substring 12 2 date;
|
|
||||||
in
|
|
||||||
"${year}-${month}-${day} ${hour}:${minute}:${second} UTC";
|
|
||||||
in
|
|
||||||
{
|
|
||||||
system.nixos.label = "${config.system.nixos.release}-haccfiles-${self.shortRev or self.dirtyShortRev}";
|
|
||||||
users.motd = ''
|
|
||||||
Welcome to ${config.networking.hostName}, running NixOS ${config.system.nixos.release}!
|
|
||||||
Built from haccfiles ${self.rev or self.dirtyRev}.
|
|
||||||
Last commit was at ${formatDate self.lastModifiedDate}.
|
|
||||||
${if self ? dirtyRev then "\nPlease remember to commit your changes.\n" else ""}
|
|
||||||
'';
|
|
||||||
|
|
||||||
# used by monit
|
|
||||||
environment.etc."haccfiles-commit".text = self.rev or self.dirtyRev;
|
|
||||||
environment.etc."haccfiles-timestamp".text = builtins.toString self.lastModified;
|
|
||||||
}
|
|
|
@ -14,5 +14,12 @@
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# I /suspect/ this is not actually needed.
|
||||||
|
# TODO: find spoons to deal with potential breakage, test removing this
|
||||||
|
networking.defaultGateway = {
|
||||||
|
address = "192.168.100.1";
|
||||||
|
interface = "eth0";
|
||||||
|
};
|
||||||
|
|
||||||
system.stateVersion = lib.mkDefault "21.05";
|
system.stateVersion = lib.mkDefault "21.05";
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,95 +0,0 @@
|
||||||
{ config, lib, pkgs, modules, profiles, sources, nixosSystem, ... }:
|
|
||||||
|
|
||||||
let
|
|
||||||
mkIPv4 = index: local:
|
|
||||||
"192.168.${if local then "100" else "101"}.${toString index}";
|
|
||||||
mkIPv6 = index: local:
|
|
||||||
"fd00::${if local then "100" else "101"}:${toString index}";
|
|
||||||
|
|
||||||
evalConfig = nixosConfig: (nixosSystem {
|
|
||||||
inherit (config.nixpkgs) system;
|
|
||||||
modules = [
|
|
||||||
nixosConfig
|
|
||||||
modules.nopersist
|
|
||||||
profiles.container
|
|
||||||
{ nixpkgs.pkgs = lib.mkForce pkgs; }
|
|
||||||
];
|
|
||||||
specialArgs = {
|
|
||||||
inherit modules sources;
|
|
||||||
};
|
|
||||||
}).config.system.build.toplevel;
|
|
||||||
|
|
||||||
in {
|
|
||||||
options.hacc.containers = with lib.options;
|
|
||||||
mkOption {
|
|
||||||
description = ''
|
|
||||||
hacc-specific containers. These are a thin wrapper around "normal" nixos containers:
|
|
||||||
- they automatically get an IPv4/IPv6 address assigned
|
|
||||||
(note that these are not guaranteed to be stable across config changes,
|
|
||||||
so please use {option}`containers.<name>.hostAddress` & friends to
|
|
||||||
reference them elsewhere)
|
|
||||||
- they set a couple default options (e.g. ephemeral, autoStart, privateNetwork)
|
|
||||||
- they are evaluated with our own version of {nix}`evalConfig`, which includes a
|
|
||||||
couple more modules by default, use our version of `nixpkgs`, and includes the
|
|
||||||
{nix}`profiles.containers` profile setting sane defaults for containers.
|
|
||||||
'';
|
|
||||||
default = { };
|
|
||||||
type = with lib.types;
|
|
||||||
types.attrsOf (types.submodule {
|
|
||||||
options = {
|
|
||||||
bindToPersist = mkOption {
|
|
||||||
default = true;
|
|
||||||
type = types.bool;
|
|
||||||
description =
|
|
||||||
"Wether to mount /persist/containers/<name> at /persist into this container.";
|
|
||||||
};
|
|
||||||
|
|
||||||
bindSecrets = mkOption {
|
|
||||||
default = false;
|
|
||||||
type = types.bool;
|
|
||||||
description =
|
|
||||||
"Whether to mount /run/secrets/<name> at /secrets into this container.";
|
|
||||||
};
|
|
||||||
|
|
||||||
config = mkOption {
|
|
||||||
type = types.unspecified;
|
|
||||||
description =
|
|
||||||
"The container's config, to be evaluated with our own {nix}`evalConfig`.";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
# wrapped into imap1, which enumerates the containers; IP addresses are then
|
|
||||||
# simply assigned based on the order the containers are in the list.
|
|
||||||
config.containers = lib.mkMerge (lib.imap1
|
|
||||||
(index: { name, value }: let container = value; in {
|
|
||||||
${name} = {
|
|
||||||
hostAddress = mkIPv4 index false;
|
|
||||||
localAddress = mkIPv4 index true;
|
|
||||||
hostAddress6 = mkIPv6 index false;
|
|
||||||
localAddress6 = mkIPv6 index true;
|
|
||||||
|
|
||||||
privateNetwork = true;
|
|
||||||
autoStart = true;
|
|
||||||
ephemeral = true;
|
|
||||||
|
|
||||||
bindMounts = lib.mkMerge [
|
|
||||||
(lib.mkIf container.bindToPersist {
|
|
||||||
"/persist" = {
|
|
||||||
hostPath = "/persist/containers/${name}";
|
|
||||||
isReadOnly = false;
|
|
||||||
};
|
|
||||||
})
|
|
||||||
(lib.mkIf container.bindSecrets {
|
|
||||||
"/secrets" = {
|
|
||||||
hostPath = "/run/secrets/${name}";
|
|
||||||
isReadOnly = true;
|
|
||||||
};
|
|
||||||
})
|
|
||||||
];
|
|
||||||
|
|
||||||
path = evalConfig container.config;
|
|
||||||
};
|
|
||||||
}) (lib.attrsToList config.hacc.containers));
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
{ config, pkgs, lib, ... }:
|
|
||||||
|
|
||||||
with lib;
|
|
||||||
|
|
||||||
let cfg = config.hacc.encboot;
|
|
||||||
|
|
||||||
in {
|
|
||||||
options = {
|
|
||||||
hacc.encboot = {
|
|
||||||
enable = mkOption {
|
|
||||||
type = types.bool;
|
|
||||||
default = false;
|
|
||||||
};
|
|
||||||
networkDrivers = mkOption { type = with types; listOf str; };
|
|
||||||
dataset = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = "zroot";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
|
||||||
boot.initrd.kernelModules = cfg.networkDrivers;
|
|
||||||
|
|
||||||
boot.initrd.network = {
|
|
||||||
enable = true;
|
|
||||||
ssh = {
|
|
||||||
enable = true;
|
|
||||||
port = 2222;
|
|
||||||
authorizedKeys = with lib;
|
|
||||||
concatLists (mapAttrsToList (name: user:
|
|
||||||
if elem "wheel" user.extraGroups then
|
|
||||||
user.openssh.authorizedKeys.keys
|
|
||||||
else
|
|
||||||
[ ]) config.users.users);
|
|
||||||
hostKeys = [ /etc/ssh/encboot_host ];
|
|
||||||
};
|
|
||||||
|
|
||||||
postCommands = ''
|
|
||||||
zpool import ${cfg.dataset}
|
|
||||||
echo "zfs load-key -a; killall zfs && exit" >> /root/.profile
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,52 +0,0 @@
|
||||||
{ config, lib, pkgs, modules, ... }:
|
|
||||||
|
|
||||||
with lib;
|
|
||||||
|
|
||||||
{
|
|
||||||
imports = [ modules.bindMounts ];
|
|
||||||
|
|
||||||
users.mutableUsers = false;
|
|
||||||
|
|
||||||
boot.initrd = mkIf (config.fileSystems."/".fsType == "zfs") {
|
|
||||||
network.ssh.hostKeys = mkIf config.hacc.encboot.enable
|
|
||||||
(mkForce [ /persist/ssh/encboot_host ]);
|
|
||||||
|
|
||||||
postDeviceCommands = mkIf (!config.boot.initrd.systemd.enable)
|
|
||||||
(mkAfter ''
|
|
||||||
zfs rollback -r ${config.fileSystems."/".device}@blank
|
|
||||||
'');
|
|
||||||
|
|
||||||
systemd = mkIf config.boot.initrd.systemd.enable {
|
|
||||||
storePaths = [ pkgs.zfs ];
|
|
||||||
services.rollback = {
|
|
||||||
description = "Rollback ZFS datasets to a pristine state";
|
|
||||||
wantedBy = [ "initrd.target" ];
|
|
||||||
after = [ "zfs-import-${head (splitString "/" config.fileSystems."/".device)}.service" ];
|
|
||||||
before = [ "sysroot.mount" ];
|
|
||||||
path = [ pkgs.zfs ];
|
|
||||||
unitConfig.DefaultDependencies = "no";
|
|
||||||
serviceConfig.Type = "oneshot";
|
|
||||||
script = ''
|
|
||||||
zfs rollback -r ${config.fileSystems."/".device}@blank && echo "rollback complete"
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
services.openssh = {
|
|
||||||
hostKeys = [
|
|
||||||
{
|
|
||||||
path = "/persist/ssh/ssh_host_ed25519_key";
|
|
||||||
type = "ed25519";
|
|
||||||
}
|
|
||||||
{
|
|
||||||
path = "/persist/ssh/ssh_host_rsa_key";
|
|
||||||
type = "rsa";
|
|
||||||
bits = 4096;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
services.postgresql.dataDir =
|
|
||||||
"/persist/postgresql/${config.services.postgresql.package.psqlSchema}";
|
|
||||||
}
|
|
|
@ -1,64 +0,0 @@
|
||||||
{ config, options, lib, pkgs, ... }:
|
|
||||||
|
|
||||||
let
|
|
||||||
checkHash = pkgs.writeScriptBin "check-commit-hash" ''
|
|
||||||
#!${lib.getExe pkgs.fish}
|
|
||||||
set wanted (${lib.getExe pkgs.curl} -s https://git.infra4future.de/api/v1/repos/hacc/haccfiles/branches/main \
|
|
||||||
-H 'accept: application/json' | jq -r .commit.id)
|
|
||||||
|
|
||||||
if test $status != 0
|
|
||||||
echo "could not reach git.infra4future.de"
|
|
||||||
exit 2
|
|
||||||
end
|
|
||||||
|
|
||||||
set actual (cat /etc/haccfiles-commit)
|
|
||||||
if test $status != 0
|
|
||||||
echo "/etc/haccfiles-commit does not exist??"
|
|
||||||
exit 2
|
|
||||||
end
|
|
||||||
|
|
||||||
if test $actual != $wanted
|
|
||||||
echo "parsons was built on $actual, but commit on main is $wanted"
|
|
||||||
exit 1
|
|
||||||
end
|
|
||||||
'';
|
|
||||||
|
|
||||||
checkDeployAge = pkgs.writeScriptBin "check-deploy-age" ''
|
|
||||||
#!${lib.getExe pkgs.fish}
|
|
||||||
|
|
||||||
set date (date +%s)
|
|
||||||
# we do this indirection here so monit's config won't change on each deploy
|
|
||||||
set deploytimestamp (cat /etc/haccfiles-timestamp)
|
|
||||||
set age (expr $date - $deploytimestamp)
|
|
||||||
|
|
||||||
if test $age -ge (expr 3600 \* 24 \* 10)
|
|
||||||
echo "${config.networking.hostName} has not been deployed since 10 days, perhaps someone should do updates?"
|
|
||||||
exit 1
|
|
||||||
end
|
|
||||||
'';
|
|
||||||
in
|
|
||||||
{
|
|
||||||
mailserver.monitoring = {
|
|
||||||
enable = true;
|
|
||||||
alertAddress = "admin@hacc.space";
|
|
||||||
config = (lib.replaceStrings ["port 22"] ["port ${toString (lib.head config.services.openssh.ports)}"] options.mailserver.monitoring.config.default);
|
|
||||||
};
|
|
||||||
|
|
||||||
services.monit.config = ''
|
|
||||||
check host onlyoffice with address onlyoffice.infra4future.de
|
|
||||||
start program "/run/current-system/sw/bin/lxc-start -n onlyoffice -f /persist/lxc/onlyoffice/config"
|
|
||||||
stop program "/run/current-system/sw/bin/lxc-stop -n onlyoffice"
|
|
||||||
if failed port 443 protocol https status = 302
|
|
||||||
then restart
|
|
||||||
|
|
||||||
check program deployed-commit-on-main path ${lib.getExe checkHash}
|
|
||||||
if status == 1 for 64 cycles then alert
|
|
||||||
if status == 2 for 3 cycles then alert
|
|
||||||
|
|
||||||
check program is-system-running path ${pkgs.systemd}/bin/systemctl is-system-running
|
|
||||||
if status != 0 then alert
|
|
||||||
|
|
||||||
check program check-deploy-age path ${lib.getExe checkDeployAge}
|
|
||||||
if status == 1 then alert
|
|
||||||
'';
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
{ config, lib, pkgs, ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
networking.firewall.enable = true;
|
|
||||||
networking.firewall.logRefusedConnections = false;
|
|
||||||
networking.nat.enable = true;
|
|
||||||
|
|
||||||
networking.nftables.enable = true;
|
|
||||||
networking.nftables.tables.nat = {
|
|
||||||
family = "ip";
|
|
||||||
content = ''
|
|
||||||
chain prerouting {
|
|
||||||
type nat hook prerouting priority -100
|
|
||||||
iifname enp35s0 tcp dport { 22 } dnat ${config.containers.forgejo.localAddress}:22
|
|
||||||
}
|
|
||||||
chain postrouting {
|
|
||||||
type nat hook postrouting priority 100
|
|
||||||
iifname lxcbr0 oifname enp35s0 masquerade
|
|
||||||
iifname ve-* oifname enp35s0 masquerade
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
{ config, pkgs, ... }:
|
|
||||||
|
|
||||||
|
|
||||||
{
|
|
||||||
hacc.websites = {
|
|
||||||
enable = true;
|
|
||||||
directory = "${../.}/websites";
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
services.nginx.virtualHosts."parsons.hacc.space" = {
|
|
||||||
enableACME = true;
|
|
||||||
forceSSL = true;
|
|
||||||
locations."/~stuebinm/".root = "/persist/www/";
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,137 +0,0 @@
|
||||||
{ config, lib, pkgs, ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
sops.secrets = {
|
|
||||||
"s4f-conference/env" = {};
|
|
||||||
};
|
|
||||||
|
|
||||||
hacc.containers.s4f-conference = {
|
|
||||||
bindSecrets = true;
|
|
||||||
|
|
||||||
config = { config, lib, pkgs, ... }: {
|
|
||||||
systemd.services.mattermost.serviceConfig.EnvironmentFile =
|
|
||||||
lib.mkForce "/secrets/env";
|
|
||||||
|
|
||||||
services.mattermost = {
|
|
||||||
enable = true;
|
|
||||||
siteUrl = "https://s4f-conference.infra4future.de";
|
|
||||||
siteName = "Scientists for Future Chat";
|
|
||||||
listenAddress = "0.0.0.0:3000";
|
|
||||||
mutableConfig = false;
|
|
||||||
|
|
||||||
statePath = "/persist/mattermost";
|
|
||||||
|
|
||||||
extraConfig = {
|
|
||||||
ServiceSettings = {
|
|
||||||
TrustedProxyIPHeader = [ "X-Forwarded-For" "X-Real-Ip" ];
|
|
||||||
EnableEmailInvitations = true;
|
|
||||||
};
|
|
||||||
TeamSettings = {
|
|
||||||
EnableUserCreation = true;
|
|
||||||
MaxUsersPerTeam = 2500;
|
|
||||||
EnableUserDeactivation = true;
|
|
||||||
EnableOpenServer = false;
|
|
||||||
};
|
|
||||||
PasswordSettings = {
|
|
||||||
MinimumLength = 10;
|
|
||||||
};
|
|
||||||
FileSettings = {
|
|
||||||
EnableFileAttachments = true;
|
|
||||||
MaxFileSize = 52428800;
|
|
||||||
DriverName = "local";
|
|
||||||
Directory = "/persist/upload-storage";
|
|
||||||
EnablePublicLink = true;
|
|
||||||
PublicLinkSalt = "3k7p3yxdhz6798b3b9openfr9rn3ymwu";
|
|
||||||
};
|
|
||||||
EmailSettings = {
|
|
||||||
EnableSignUpWithEmail = true;
|
|
||||||
EnableSignInWithEmail = true;
|
|
||||||
EnableSignInWithUsername = true;
|
|
||||||
SendEmailNotifications = true;
|
|
||||||
FeedbackName = "mattermost";
|
|
||||||
FeedbackEmail = "mattermost@infra4future.de";
|
|
||||||
ReplyToAddress = "mattermost@infra4future.de";
|
|
||||||
FeedbackOrganization = "∆infra4future.de";
|
|
||||||
EnableSMTPAuth = true;
|
|
||||||
SMTPUsername = "noreply@infra4future.de";
|
|
||||||
SMTPServer = "mail.hacc.space";
|
|
||||||
SMTPPort = "465";
|
|
||||||
SMTPServerTimeout = 10;
|
|
||||||
ConnectionSecurity = "TLS";
|
|
||||||
};
|
|
||||||
RateLimitSettings.Enable = false;
|
|
||||||
PrivacySettings = {
|
|
||||||
ShowEmailAddress = false;
|
|
||||||
ShowFullName = true;
|
|
||||||
};
|
|
||||||
# to disable the extra landing page advertising the app
|
|
||||||
NativeAppSettings = {
|
|
||||||
AppDownloadLink = "";
|
|
||||||
AndroidAppDownloadLink = "";
|
|
||||||
IosAppDownloadLink = "";
|
|
||||||
};
|
|
||||||
LogSettings = {
|
|
||||||
EnableConsole = true;
|
|
||||||
ConsoleLevel = "ERROR";
|
|
||||||
EnableDiagnostics = false;
|
|
||||||
EnableWebhookDebugging = false;
|
|
||||||
};
|
|
||||||
SupportSettings = {
|
|
||||||
TermsOfServiceLink = "https://infra4future.de/nutzungsbedingungen.html";
|
|
||||||
PrivacyPolicyLink = "https://infra4future.de/nutzungsbedingungen.html";
|
|
||||||
AboutLink = "https://infra4future.de";
|
|
||||||
SupportEmail = "info@infra4future.de";
|
|
||||||
CustomTermsOfServiceEnabled = false;
|
|
||||||
EnableAskCommunityLink = true;
|
|
||||||
};
|
|
||||||
AnnouncementSettings.EnableBanner = false;
|
|
||||||
ComplianceSettings.Enable = false;
|
|
||||||
ClusterSettings.Enable = false;
|
|
||||||
MetricsSettings.Enable = false;
|
|
||||||
GuestAccountsSettings.Enable = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
localDatabaseCreate = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
services.postgresql = {
|
|
||||||
enable = lib.mkForce true; # mattermost sets this to false. wtf.
|
|
||||||
package = pkgs.postgresql_15;
|
|
||||||
ensureDatabases = [ "mattermost" ];
|
|
||||||
ensureUsers = [ {
|
|
||||||
name = "mattermost";
|
|
||||||
ensureDBOwnership = true;
|
|
||||||
} ];
|
|
||||||
|
|
||||||
authentication = lib.mkForce ''
|
|
||||||
# Generated file; do not edit!
|
|
||||||
local all all trust
|
|
||||||
host mattermost mattermost ::1/128 trust
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
services.postgresqlBackup = {
|
|
||||||
enable = true;
|
|
||||||
databases = [ "mattermost" ];
|
|
||||||
startAt = "*-*-* 23:45:00";
|
|
||||||
location = "/persist/backups/postgres";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
services.nginx.virtualHosts."s4f-conference.infra4future.de" = {
|
|
||||||
locations."/" = {
|
|
||||||
proxyPass = "http://${config.containers.s4f-conference.localAddress}:3000";
|
|
||||||
proxyWebsockets = true;
|
|
||||||
extraConfig = ''
|
|
||||||
# Mattermost CSR Patch
|
|
||||||
proxy_hide_header Content-Security-Policy;
|
|
||||||
proxy_hide_header X-Frame-Options;
|
|
||||||
proxy_redirect off;
|
|
||||||
|
|
||||||
client_max_body_size 100M;
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
forceSSL = true;
|
|
||||||
enableACME = true;
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,102 +0,0 @@
|
||||||
{ config, lib, pkgs, ... }:
|
|
||||||
|
|
||||||
let
|
|
||||||
tracktrain-config = ''
|
|
||||||
dbstring: "dbname=tracktrain"
|
|
||||||
gtfs: /persist/gtfs.zip
|
|
||||||
assets: ${pkgs.tracktrain}/assets
|
|
||||||
|
|
||||||
warp:
|
|
||||||
port: 4000
|
|
||||||
|
|
||||||
login:
|
|
||||||
enable: true
|
|
||||||
url: https://login.infra4future.de
|
|
||||||
clientName: tracktrain
|
|
||||||
# clientSecret defined in env file
|
|
||||||
|
|
||||||
logging:
|
|
||||||
ntfyTopic: ping.stuebinm.eu/monit
|
|
||||||
name: ilztalbahn
|
|
||||||
'';
|
|
||||||
in
|
|
||||||
{
|
|
||||||
sops.secrets = {
|
|
||||||
"tracktrain/env" = {};
|
|
||||||
};
|
|
||||||
|
|
||||||
services.nginx.virtualHosts."tracktrain.ilztalbahn.eu" = {
|
|
||||||
enableACME = true;
|
|
||||||
forceSSL = true;
|
|
||||||
locations."/" = {
|
|
||||||
proxyPass = "http://${config.containers.tracktrain.localAddress}:4000";
|
|
||||||
proxyWebsockets = true;
|
|
||||||
};
|
|
||||||
# note: this shadows the /metrics endpoint of tracktrain
|
|
||||||
# in case you remove this, please consider putting something
|
|
||||||
# else here to keep it from being publicly scrapable
|
|
||||||
locations."/metrics/" = {
|
|
||||||
proxyPass = "http://${config.containers.tracktrain.localAddress}:2342";
|
|
||||||
proxyWebsockets = true;
|
|
||||||
extraConfig = ''
|
|
||||||
rewrite ^/metrics/(.*) /$1 break;
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
hacc.containers.tracktrain = {
|
|
||||||
bindSecrets = true;
|
|
||||||
|
|
||||||
config = { config, lib, pkgs, ... }: {
|
|
||||||
|
|
||||||
systemd.services.tracktrain = {
|
|
||||||
enable = true;
|
|
||||||
|
|
||||||
description = "tracks trains, hopefully";
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
requires = [ "network.target" ];
|
|
||||||
after = [ "network.target" ];
|
|
||||||
serviceConfig = {
|
|
||||||
Type = "simple";
|
|
||||||
EnvironmentFile = "/secrets/env";
|
|
||||||
DynamicUser = true;
|
|
||||||
};
|
|
||||||
path = [ pkgs.wget pkgs.ntfy-sh ];
|
|
||||||
script = ''
|
|
||||||
cd /tmp
|
|
||||||
ln -sf ${pkgs.writeText "tracktrain-config.yaml" tracktrain-config} config.yaml
|
|
||||||
${pkgs.tracktrain}/bin/tracktrain +RTS -T
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
services.postgresql = {
|
|
||||||
enable = true;
|
|
||||||
package = pkgs.postgresql_15;
|
|
||||||
ensureDatabases = [ "tracktrain" ];
|
|
||||||
ensureUsers = [ {
|
|
||||||
name = "tracktrain";
|
|
||||||
ensureDBOwnership = true;
|
|
||||||
} ];
|
|
||||||
authentication = ''
|
|
||||||
local all all trust
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
services.prometheus = {
|
|
||||||
enable = true;
|
|
||||||
port = 9001;
|
|
||||||
scrapeConfigs = [ {
|
|
||||||
job_name = "tracktrain";
|
|
||||||
static_configs = [{
|
|
||||||
targets = [ "0.0.0.0:4000" ];
|
|
||||||
}];
|
|
||||||
} ];
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services.grafana.serviceConfig.EnvironmentFile =
|
|
||||||
"/secrets/env";
|
|
||||||
hacc.bindToPersist = [ "/var/lib/grafana" ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
|
@ -3,35 +3,51 @@
|
||||||
let
|
let
|
||||||
pkgs = import sources.nixpkgs args;
|
pkgs = import sources.nixpkgs args;
|
||||||
oldstable = import sources.nixpkgs-oldstable args;
|
oldstable = import sources.nixpkgs-oldstable args;
|
||||||
unstable = import sources.nixpkgs-unstable args;
|
|
||||||
|
|
||||||
callPackage = pkgs.lib.callPackageWith (pkgs // newpkgs);
|
callPackage = pkgs.lib.callPackageWith (pkgs // newpkgs);
|
||||||
|
|
||||||
newpkgs = {
|
newpkgs = {
|
||||||
|
|
||||||
mattermost = callPackage ./mattermost.nix {
|
mattermost = callPackage ./mattermost {inherit sources;};
|
||||||
buildGoModule = unstable.buildGo122Module;
|
|
||||||
};
|
|
||||||
|
|
||||||
morph = callPackage ./morph.nix {
|
|
||||||
buildGoModule = unstable.buildGo122Module;
|
|
||||||
};
|
|
||||||
|
|
||||||
forgejo = unstable.forgejo;
|
|
||||||
|
|
||||||
tracktrain = import sources.tracktrain {
|
tracktrain = import sources.tracktrain {
|
||||||
nixpkgs = unstable;
|
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
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
uffd = oldstable.callPackage ./uffd { };
|
uffd = oldstable.callPackage ./uffd { };
|
||||||
|
|
||||||
hacc-scripts = callPackage ./scripts {};
|
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;
|
||||||
|
|
||||||
# TODO: once on nixos 24.05, remove this inherit
|
|
||||||
inherit (unstable) lix;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
in pkgs.extend(_: _: newpkgs)
|
in pkgs.extend(_: _: newpkgs)
|
||||||
|
|
|
@ -1,85 +0,0 @@
|
||||||
{ lib
|
|
||||||
, buildGoModule
|
|
||||||
, fetchFromGitHub
|
|
||||||
, nix-update-script
|
|
||||||
, fetchurl
|
|
||||||
, nixosTests
|
|
||||||
}:
|
|
||||||
|
|
||||||
buildGoModule rec {
|
|
||||||
pname = "mattermost";
|
|
||||||
# ESR releases only.
|
|
||||||
# See https://docs.mattermost.com/upgrade/extended-support-release.html
|
|
||||||
# When a new ESR version is available (e.g. 8.1.x -> 9.5.x), update
|
|
||||||
# the version regex in passthru.updateScript as well.
|
|
||||||
version = "9.11.5";
|
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
|
||||||
owner = "mattermost";
|
|
||||||
repo = "mattermost";
|
|
||||||
rev = "v${version}";
|
|
||||||
hash = "sha256-bLZFeG6kBVP0ws50wtBam/bO206sQnz6va8PATAoRAQ=";
|
|
||||||
};
|
|
||||||
|
|
||||||
# Needed because buildGoModule does not support go workspaces yet.
|
|
||||||
# We use go 1.22's workspace vendor command, which is not yet available
|
|
||||||
# in the default version of go used in nixpkgs, nor is it used by upstream:
|
|
||||||
# https://github.com/mattermost/mattermost/issues/26221#issuecomment-1945351597
|
|
||||||
overrideModAttrs = (_: {
|
|
||||||
buildPhase = ''
|
|
||||||
make setup-go-work
|
|
||||||
go work vendor -e
|
|
||||||
'';
|
|
||||||
});
|
|
||||||
|
|
||||||
webapp = fetchurl {
|
|
||||||
url = "https://releases.mattermost.com/${version}/mattermost-${version}-linux-amd64.tar.gz";
|
|
||||||
hash = "sha256-jyaJUN8wpuBivKNdm7f1mYwygO8xC+Zxy0SdkDovdsA=";
|
|
||||||
};
|
|
||||||
|
|
||||||
vendorHash = "sha256-Gwv6clnq7ihoFC8ox8iEM5xp/us9jWUrcmqA9/XbxBE=";
|
|
||||||
|
|
||||||
modRoot = "./server";
|
|
||||||
preBuild = ''
|
|
||||||
make setup-go-work
|
|
||||||
'';
|
|
||||||
|
|
||||||
subPackages = [ "cmd/mattermost" ];
|
|
||||||
offlineCache = webapp;
|
|
||||||
|
|
||||||
tags = [ "production" ];
|
|
||||||
|
|
||||||
ldflags = [
|
|
||||||
"-s"
|
|
||||||
"-w"
|
|
||||||
"-X github.com/mattermost/mattermost/server/public/model.Version=${version}"
|
|
||||||
"-X github.com/mattermost/mattermost/server/public/model.BuildNumber=${version}-nixpkgs"
|
|
||||||
"-X github.com/mattermost/mattermost/server/public/model.BuildDate=1970-01-01"
|
|
||||||
"-X github.com/mattermost/mattermost/server/public/model.BuildHash=v${version}"
|
|
||||||
"-X github.com/mattermost/mattermost/server/public/model.BuildHashEnterprise=none"
|
|
||||||
"-X github.com/mattermost/mattermost/server/public/model.BuildEnterpriseReady=false"
|
|
||||||
];
|
|
||||||
|
|
||||||
postInstall = ''
|
|
||||||
tar --strip 1 --directory $out -xf $webapp \
|
|
||||||
mattermost/{client,i18n,fonts,templates,config}
|
|
||||||
|
|
||||||
# For some reason a bunch of these files are executable
|
|
||||||
find $out/{client,i18n,fonts,templates,config} -type f -exec chmod -x {} \;
|
|
||||||
'';
|
|
||||||
|
|
||||||
passthru = {
|
|
||||||
updateScript = nix-update-script {
|
|
||||||
extraArgs = [ "--version-regex" "^v(9\.11\.([0-9.]+))" ];
|
|
||||||
};
|
|
||||||
tests.mattermost = nixosTests.mattermost;
|
|
||||||
};
|
|
||||||
|
|
||||||
meta = with lib; {
|
|
||||||
description = "Mattermost is an open source platform for secure collaboration across the entire software development lifecycle";
|
|
||||||
homepage = "https://www.mattermost.org";
|
|
||||||
license = with licenses; [ agpl3Only asl20 ];
|
|
||||||
maintainers = with maintainers; [ ryantm numinit kranzes mgdelacroix ];
|
|
||||||
mainProgram = "mattermost";
|
|
||||||
};
|
|
||||||
}
|
|
56
pkgs/mattermost/default.nix
Normal file
56
pkgs/mattermost/default.nix
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
{ stdenv, fetchurl, fetchFromGitHub, buildGoModule, buildEnv, lib, sources }:
|
||||||
|
|
||||||
|
let
|
||||||
|
version = "8.1.3";
|
||||||
|
|
||||||
|
mattermost-server = buildGoModule rec {
|
||||||
|
pname = "mattermost-server";
|
||||||
|
inherit version;
|
||||||
|
|
||||||
|
src = "${sources.mattermost-server}/server";
|
||||||
|
|
||||||
|
vendorSha256 = "sha256-uHKd8shLDVd+zjRhEJcxAn+H9e9jqEM8XXqYx7B4hiQ=";
|
||||||
|
|
||||||
|
subPackages = [ "cmd/mattermost" ];
|
||||||
|
|
||||||
|
ldflags = [
|
||||||
|
"-s"
|
||||||
|
"-w"
|
||||||
|
"-X github.com/mattermost/mattermost/server/public/model.Version=${version}"
|
||||||
|
"-X github.com/mattermost/mattermost/server/public/model.BuildNumber=${version}-haccfiles"
|
||||||
|
"-X github.com/mattermost/mattermost/server/public/model.BuildDate=1970-01-01"
|
||||||
|
"-X github.com/mattermost/mattermost/server/public/model.BuildHash=v${version}"
|
||||||
|
"-X github.com/mattermost/mattermost/server/public/model.BuildHashEnterprise=v${version}"
|
||||||
|
"-X github.com/mattermost/mattermost/server/public/model.BuildEnterpriseReady=false"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
mattermost-webapp = stdenv.mkDerivation {
|
||||||
|
pname = "mattermost-webapp";
|
||||||
|
inherit version;
|
||||||
|
|
||||||
|
src = sources.mattermost-webapp;
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
mkdir -p $out
|
||||||
|
cp -r client $out
|
||||||
|
cp -r i18n $out
|
||||||
|
cp -r fonts $out
|
||||||
|
cp -r templates $out
|
||||||
|
cp -r config $out
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
in
|
||||||
|
buildEnv {
|
||||||
|
name = "mattermost-${version}";
|
||||||
|
paths = [ mattermost-server mattermost-webapp ];
|
||||||
|
|
||||||
|
meta = with lib; {
|
||||||
|
description = "Open-source, self-hosted Slack-alternative";
|
||||||
|
homepage = "https://www.mattermost.org";
|
||||||
|
license = with licenses; [ agpl3 asl20 ];
|
||||||
|
maintainers = with maintainers; [ fpletz ryantm ];
|
||||||
|
platforms = platforms.unix;
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,33 +0,0 @@
|
||||||
{ buildGoModule
|
|
||||||
, fetchFromGitHub
|
|
||||||
}:
|
|
||||||
|
|
||||||
buildGoModule rec {
|
|
||||||
pname = "mattermost-morph";
|
|
||||||
version = "1.1.0";
|
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
|
||||||
owner = "mattermost";
|
|
||||||
repo = "morph";
|
|
||||||
rev = "v${version}";
|
|
||||||
hash = "sha256-Orh/a9OlUVIlDdLXRpDAnHUmWRiM1N2oO+dijbuJzx8=";
|
|
||||||
};
|
|
||||||
|
|
||||||
vendorHash = null;
|
|
||||||
|
|
||||||
subPackages = [ "cmd/morph" ];
|
|
||||||
|
|
||||||
tags = [ "production" ];
|
|
||||||
|
|
||||||
ldflags = [
|
|
||||||
"-s"
|
|
||||||
"-w"
|
|
||||||
"-X github.com/mattermost/mattermost/server/public/model.Version=${version}"
|
|
||||||
"-X github.com/mattermost/mattermost/server/public/model.BuildNumber=${version}-nixpkgs"
|
|
||||||
"-X github.com/mattermost/mattermost/server/public/model.BuildDate=1970-01-01"
|
|
||||||
"-X github.com/mattermost/mattermost/server/public/model.BuildHash=v${version}"
|
|
||||||
"-X github.com/mattermost/mattermost/server/public/model.BuildHashEnterprise=none"
|
|
||||||
"-X github.com/mattermost/mattermost/server/public/model.BuildEnterpriseReady=false"
|
|
||||||
];
|
|
||||||
|
|
||||||
}
|
|
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
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
{ stdenvNoCC, gauche, fish }:
|
|
||||||
|
|
||||||
stdenvNoCC.mkDerivation {
|
|
||||||
name = "hacc-utility-scripts";
|
|
||||||
|
|
||||||
src = ./.;
|
|
||||||
|
|
||||||
buildInputs = [ gauche fish ];
|
|
||||||
|
|
||||||
installPhase = ''
|
|
||||||
mkdir -p $out/bin
|
|
||||||
fish -n $out/bin/*.fish
|
|
||||||
cp *.{scm,fish} $out/bin
|
|
||||||
chmod +x $out/bin/*
|
|
||||||
'';
|
|
||||||
}
|
|
|
@ -1,47 +0,0 @@
|
||||||
#!/usr/bin/env fish
|
|
||||||
|
|
||||||
source /run/secrets/auamost/secrets.fish
|
|
||||||
|
|
||||||
for i in (seq 1 (count $groups))
|
|
||||||
set team $teams[$i]
|
|
||||||
set group $groups[$i]
|
|
||||||
set users (curl -u $uffd_token --basic https://login.infra4future.de/api/v1/getusers -d group="$group")
|
|
||||||
set usernames (echo "$users" | jq -c "[.[] | .loginname]")
|
|
||||||
for user in (echo "$users" | jq -c ".[]")
|
|
||||||
set id (echo "$user" | jq .id)
|
|
||||||
set username (echo "$user" | jq .loginname)
|
|
||||||
set email (echo "$user" | jq .email)
|
|
||||||
curl -H $mattermost_token \
|
|
||||||
-H "Content-Type: application/json" https://mattermost.infra4future.de/api/v4/users \
|
|
||||||
-d '{"email": '"$email"', "username": '"$username"', "auth_service": "gitlab", "auth_data": "'"$id"'"}'
|
|
||||||
end
|
|
||||||
set userids (curl -H $mattermost_token \
|
|
||||||
-H "Content-Type: application/json" https://mattermost.infra4future.de/api/v4/users/usernames \
|
|
||||||
-d "$usernames" | jq '[.[] | {user_id: .id, team_id: "'$team'"} ]')
|
|
||||||
curl -H $mattermost_token \
|
|
||||||
-H "Content-Type: application/json" https://mattermost.infra4future.de/api/v4/teams/"$team"/members/batch \
|
|
||||||
-d "$userids"
|
|
||||||
|
|
||||||
if test "$group" = "hacc"
|
|
||||||
continue
|
|
||||||
end
|
|
||||||
|
|
||||||
set current_members (curl -H $mattermost_token \
|
|
||||||
-H "Content-Type: application/json" https://mattermost.infra4future.de/api/v4/teams/"$team"/members | jq '[.[] | .user_id]')
|
|
||||||
|
|
||||||
# membership relations don't contain e.g. usernames, so fetch those, too
|
|
||||||
set current_users (curl -H $mattermost_token \
|
|
||||||
-H "Content-Type: application/json" https://mattermost.infra4future.de/api/v4/users/ids \
|
|
||||||
-d "$current_members" | jq -c '.[]')
|
|
||||||
|
|
||||||
set userids (echo "$userids" | jq -c ".[].user_id")
|
|
||||||
for member in $current_users
|
|
||||||
set id (echo $member | jq .id)
|
|
||||||
if not contains -i $id $userids > /dev/null then
|
|
||||||
set id_unquoted (echo $member | jq -r .id)
|
|
||||||
echo removing $id_unquoted (echo $member | jq '.email') from $team \($group\)
|
|
||||||
curl -X DELETE -H $mattermost_token \
|
|
||||||
-H "Content-Type: application/json" https://mattermost.infra4future.de/api/v4/teams/"$team"/members/"$id_unquoted"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,121 +0,0 @@
|
||||||
#!/usr/bin/env gosh
|
|
||||||
|
|
||||||
(use gauche.process)
|
|
||||||
(use text.csv)
|
|
||||||
(use scheme.list)
|
|
||||||
(use gauche.parseopt)
|
|
||||||
(use util.match)
|
|
||||||
|
|
||||||
(define cutoff-date "2023-01-01")
|
|
||||||
|
|
||||||
(define sqlite-path "/persist/containers/uffd/uffd/db.sqlite")
|
|
||||||
(define sqlite-query
|
|
||||||
"select displayname, mail, max(expires) as last_login from oauth2token join user on user_id=user.id group by user_id having last_login < '2023-01-01'
|
|
||||||
union all select displayname, mail, '2022' from user where not exists (select * from oauth2token where user_id = user.id);")
|
|
||||||
|
|
||||||
(define dry #f)
|
|
||||||
(define verbose #f)
|
|
||||||
(define very-verbose #f)
|
|
||||||
|
|
||||||
(define (main args)
|
|
||||||
(let-args (cdr args)
|
|
||||||
((averbose "v|verbose")
|
|
||||||
(averyverbose "very-verbose")
|
|
||||||
(adry "n|dry-run")
|
|
||||||
(help "h|help" => (cut show-help (car args)))
|
|
||||||
. restargs
|
|
||||||
)
|
|
||||||
(set! dry adry)
|
|
||||||
(set! verbose averbose)
|
|
||||||
(when averyverbose
|
|
||||||
(set! verbose #t)
|
|
||||||
(set! very-verbose #t))
|
|
||||||
(match restargs
|
|
||||||
[("admin") (do-admin-mail)]
|
|
||||||
[("send-reminder") (send-reminder-mails)]
|
|
||||||
[("list-accounts") (do-list-accounts)]
|
|
||||||
[_ (display "unknown command") (exit 1)]))
|
|
||||||
0)
|
|
||||||
|
|
||||||
(define (do-admin-mail)
|
|
||||||
(send-email "admin@hacc.space" "unused accounts list" (mk-admin-mail unused-accounts))
|
|
||||||
(when verbose
|
|
||||||
(display "done")))
|
|
||||||
|
|
||||||
(define (do-list-accounts)
|
|
||||||
(display (string-join
|
|
||||||
(map
|
|
||||||
(lambda (row) (format "~a (~a)" (list-ref row 0) (list-ref row 1)))
|
|
||||||
unused-accounts)
|
|
||||||
"\n")))
|
|
||||||
|
|
||||||
(define (send-reminder-mails)
|
|
||||||
(map (lambda (row)
|
|
||||||
(send-email (list-ref row 1) "Unbenutzter infra4future.de Account" (mk-email (list-ref row 0) (list-ref row 2))))
|
|
||||||
unused-accounts)
|
|
||||||
(when verbose
|
|
||||||
(display "done")))
|
|
||||||
|
|
||||||
|
|
||||||
(define csv-reader
|
|
||||||
(make-csv-reader #\,))
|
|
||||||
|
|
||||||
(define unused-accounts
|
|
||||||
(map (lambda (str) (with-input-from-string str csv-reader))
|
|
||||||
;; (process-output->string-list `(cat example.csv))))
|
|
||||||
(process-output->string-list `(sqlite3 -csv ,sqlite-path ,sqlite-query))))
|
|
||||||
|
|
||||||
(define (mk-email displayname last-login)
|
|
||||||
#"
|
|
||||||
Hallo ~|displayname|!
|
|
||||||
|
|
||||||
Wir haben schon lange (seit über einem Jahr; dein letzter Login war um ~|last-login|)
|
|
||||||
nichts mehr von dir gehört und würden demnächst deinen Account löschen wollen.
|
|
||||||
Solltest du ihn noch benötigen logge dich bitte einfach auf https://login.infra4future.de ein.
|
|
||||||
Falls nicht, musst du weiter nichts tun und wir werden deine Account in ca. 3 Monaten löschen.
|
|
||||||
|
|
||||||
Viele Grüße,
|
|
||||||
das Infra4Future Team
|
|
||||||
")
|
|
||||||
|
|
||||||
(define (mk-admin-mail rows)
|
|
||||||
(format #"
|
|
||||||
Meow!
|
|
||||||
|
|
||||||
this is the uffd-unused-accounts-notification.scm script. There are currently
|
|
||||||
~~s accounts which have not logged in since ~|cutoff-date|. To mass-send account
|
|
||||||
expiry reminders, invoke this script with the \"send-reminder\" option. To see a
|
|
||||||
list of these accounts, invoke it with the \"list-accounts\" option.
|
|
||||||
|
|
||||||
(invoke me,, 🥺)
|
|
||||||
" (length unused-accounts)))
|
|
||||||
|
|
||||||
; utility definitions
|
|
||||||
|
|
||||||
(define (send-email address subject text)
|
|
||||||
(when verbose
|
|
||||||
(display (format "sending email to ~a\n" address)))
|
|
||||||
(let ([text (string-append "from: admin@hacc.space\n" "subject: " subject "\n" text "\n")])
|
|
||||||
(when very-verbose
|
|
||||||
(display text))
|
|
||||||
(call-with-output-process
|
|
||||||
(if dry '(cat) `(sendmail ,address))
|
|
||||||
(lambda (port) (display text port))
|
|
||||||
:on-abnormal-exit :ignore)))
|
|
||||||
|
|
||||||
(define (show-help progname)
|
|
||||||
(display #"
|
|
||||||
~|progname|: unused account expiry helper script.
|
|
||||||
|
|
||||||
Invoke as `~|progname| [options] admin' to send a list of unused accounts to administrators.
|
|
||||||
|
|
||||||
Invoke as `~|progname| [options] send-reminder' to send a reminder email to all
|
|
||||||
currently unused accounts.
|
|
||||||
|
|
||||||
Options:
|
|
||||||
-v --verbose show which emails are being sent
|
|
||||||
--very-verbose also print emails to stdout
|
|
||||||
-n --dry-run print emails to stdout instead
|
|
||||||
-h --help show this help
|
|
||||||
"))
|
|
||||||
|
|
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;
|
||||||
|
}
|
|
@ -10,7 +10,7 @@ python3Packages.buildPythonPackage rec {
|
||||||
hash = "sha256-KP4J1bw5u7MklaPu2SBFRNyGgkKOBOpft5MMH+em5M4=";
|
hash = "sha256-KP4J1bw5u7MklaPu2SBFRNyGgkKOBOpft5MMH+em5M4=";
|
||||||
};
|
};
|
||||||
|
|
||||||
patches = [ ./forgejo-magic.patch ./fix-setuppy.patch ./fix-userinfo.patch ];
|
patches = [ ./gitea-magic.patch ./fix-setuppy.patch ./fix-userinfo.patch ];
|
||||||
|
|
||||||
propagatedBuildInputs = with python3Packages; [
|
propagatedBuildInputs = with python3Packages; [
|
||||||
flask
|
flask
|
||||||
|
|
|
@ -16,7 +16,7 @@ index d13fd42..94352be 100644
|
||||||
def userinfo():
|
def userinfo():
|
||||||
user = request.oauth.user
|
user = request.oauth.user
|
||||||
+ client = request.oauth.client_id
|
+ client = request.oauth.client_id
|
||||||
+ if client == "forgejo":
|
+ if client == "gitea":
|
||||||
+ return jsonify(
|
+ return jsonify(
|
||||||
+ id=user.unix_uid,
|
+ id=user.unix_uid,
|
||||||
+ full_name=user.displayname,
|
+ full_name=user.displayname,
|
15
secrets.yaml
15
secrets.yaml
|
@ -1,16 +1,11 @@
|
||||||
hedgedoc-hacc:
|
hedgedoc-hacc:
|
||||||
env: ENC[AES256_GCM,data:e2vSolxJNucya9QNs28gAVDBJQq5AJh7jS1nBh0UTkDnhNL8NPW1KTxcun4rM99EhiNZsz6Z9qHRMejmP4frQw==,iv:DqAGhGWYf/EpGnI79MxKmBlHMhK26zx50vXb1TbvESw=,tag:Xix499XAcAmxhNuGr2ApcA==,type:str]
|
env: ENC[AES256_GCM,data:e2vSolxJNucya9QNs28gAVDBJQq5AJh7jS1nBh0UTkDnhNL8NPW1KTxcun4rM99EhiNZsz6Z9qHRMejmP4frQw==,iv:DqAGhGWYf/EpGnI79MxKmBlHMhK26zx50vXb1TbvESw=,tag:Xix499XAcAmxhNuGr2ApcA==,type:str]
|
||||||
mattermost:
|
mattermost:
|
||||||
env: ENC[AES256_GCM,data:ftWpGl6+sUMzJJKgfcPLvbFGGn16AKUPzPn8X6DNVMLrxZIkQ23Tk3ekKLKFpQEUtQfFjVlrTfFZezWKs4nVNLg2LmQqJNGMCCax5PRwAgoAsJ7pa9ewNmHT+EIXtZEjQgVfN5786Yno5n/6JJ1lz6EiGmdn7/0rF5TLGjzig17azazS1+lkIYY=,iv:SZvGGKpVRI/odHbmgY8M6t6zCk8RgM+7EQEgRiizglA=,tag:cInsVo/QD85m+LxldyRlnA==,type:str]
|
env: ENC[AES256_GCM,data:4GcV8UOYmVUjZoYc0Nq/vEWtxtYNV81zVTEyFnZIfY1k/Ar1MU+fn5A99JLIMc8U84/QupDU7TcneiN/wqPv2jYqGS7ixSNTk+x5uUPMarzKZ04ynav6FCWEvlSF0Sz4/5s/Pvp1Qi3zdv16ZVGUHbM8/wCcaZBkSS0ofwBTIXVsVYSRPFxLehtBgwjAnD46qS+YJmszmd7V5N/adWWF34vAdfLiO6Y7KDB3jnMLOPU6Drtw9L83AW6NuOtk8crZrI1dkTD/xUC07IvMhZpZVc9ktQJqIvlk/ADs5aIp/QYrjICdYvb8xC16oV7jC/7yzXzC/UuYbCvS5gnHGMK/CsBkmM9HXmQ6mWjrfuOJEkMHSefS7O8HyrNoNDSXq0ivCr6KJmwrz7NXNAE6a6xx9LMjs5DJ8H5fda1l5TGVAdA2tg==,iv:dG4cnEtUgUxw7zS2k15p+6//Bl19WquTfFIiz5Vi/0M=,tag:cMBU8CtFBBjfcfpO709Kpg==,type:str]
|
||||||
tracktrain:
|
tracktrain:
|
||||||
env: ENC[AES256_GCM,data:W3+8qWomPgGJt5u50aAm9x/dilMpqKY11I2AdaIBTz5posc25ts0LB5S/Sxe1ROz4itpDK3QvjoFUTRhS39k4dwMr5lqXV8Ln4B+sPpvh7oBM8A5zydP8Jj1J1YqRt8++RTUmb4z41DIwb/yaZKMu6z0guXIu1yuYzcbCuk0xe/iOp6UUpfjOzzWTvxY54zY6kWcjHLiCSwD31Cd+MxMPfbUEkHt+0W+sBmYXGeEFI/6ULSB6FnGjNW6F9g=,iv:3ymah8HG+Yg6VYZZA/MRRjHDYvYJz01ezvhfQiftegg=,tag:trht+PRYfKgWJkg2wRwISQ==,type:str]
|
env: ENC[AES256_GCM,data:jaq039FNxBrsPfG/q+InYpiyl1LBdY++DlLM6UpSAwKlINucooTrHz51QrdRWhAZDqXhVTHM55Q/Zm4wazweCABiNjkXDFoZgxc5YJX+pvBct6M533xl109yD6KiYOXDqPY03u71aop8OmOAnKDp1JlzPS1otdlaN8Vd56G+,iv:nYU2rgMMG4QcJo5DnZpYZm1zr82idd7r1uTsqNiXLdA=,tag:9rdxAneYUREacXNunpTuHw==,type:str]
|
||||||
vaultwarden:
|
vaultwarden:
|
||||||
env: ENC[AES256_GCM,data:hdm91tI8WBd3es+IUbdBO69kh1pNZTNvZNFIdSZO8lm4yYMPE+Jm7EzVqwOaZRbpQaVDBg7uh5P4ODc=,iv:no7U0wQCwZOeL2pwXf2pUIgrEsEOYwqOT04LvpCl614=,tag:AGSu5M7H69x6pDM062bC6g==,type:str]
|
env: ENC[AES256_GCM,data:hdm91tI8WBd3es+IUbdBO69kh1pNZTNvZNFIdSZO8lm4yYMPE+Jm7EzVqwOaZRbpQaVDBg7uh5P4ODc=,iv:no7U0wQCwZOeL2pwXf2pUIgrEsEOYwqOT04LvpCl614=,tag:AGSu5M7H69x6pDM062bC6g==,type:str]
|
||||||
auamost:
|
|
||||||
secrets.fish: ENC[AES256_GCM,data:QBteJdVPSWa4cmu1BVWJ3AMWWH4zIv2+G83fK0QsbA/fYoIU5jobCT3USyujNz+jQaAAxA45jmQbCWNAFLl1q8hP4i9EIikVECx0VKVXPXILBND+w7zPSLldAbOugRYt2iAt1dDADZPtulKlkz7usdafbB+2igLXdyFRLfIxDTOrBuqQ+5yeofQe5k0XWRcmQQ/1AV0JrRrmLmr69VKsR932JWD8XxmI/HFyZPzWdExBSOmvnj+m4K+DV4cVmN4t6XOY0dM3gRQ95DglEuGlp/V2o3GqwY0mXCvhM1eh81u8mPALKp6Pv2i2yU35F01Puf5t1FHGDfzp0bW0xuKEywfGjAOifFkSE/3JFir434B6G0DiJNpOIl6QJ6DA8rSKfuPdccm6Or0zX8iJGRHDJmREQ05V9l0jHAAxLNuNdbsxg+8kCWVVnW+d1YDn9KW7LbFlP+sx4Ef5leUYft/lYhF4Z5Xp3arqVrlebWjWIBEuZeJTnkE3y+TdUUCs360zzWHqsipGmo1+/88CEqL52FfUOlJ4VCR45/7nYZ3RaRBWDGFW8RvwmWSFSstEcEXQ01U8lCwyn40+blfltme3KJ1f+pWMrZAKhPlOlMHCYfjd7esWI2sYcQbTZqxH49GnW6dsW/W+eiLs3zlD/Deb2CugHe63zRdlivmVPOz4zD1PXcCVpEZHoTTiJl7Om9K2mPYq9wQN41wsDUrNL9p8m9UlhWKbjBh5UU7p6F6OhF5rKH/Fs8fIaPi6B8uamTvEmiOGTUWl3vmQjBvhM8fJWoIkRB8hgCisr9OZ,iv:8jVAImjeXbXfiLKg9G0PyLMTV8cAyDmukeittqjKFpQ=,tag:fLIcsWKbdFQ/vPCgi/W3Zw==,type:str]
|
|
||||||
restic:
|
|
||||||
s3creds.env: ENC[AES256_GCM,data:9WNu5S4KmdMXdshSpawEjIexAKH6vZCPwb9xyq6xmerly1lxSfFZzgg60M0L3L+I4joLTVi23YBB8Eh6Xfx9GgxNww7w7BjMCQs/X16ecDWlb346TKf+,iv:Gu4CbXXJAlQYXRqOjIAUYmn8EU4mrvcOVc2eCh1Ikzs=,tag:1xpVIonHiAGHsXTY9liPQQ==,type:str]
|
|
||||||
system: ENC[AES256_GCM,data:RIgO0QHVjwp2D3LoU62vLzepASdsXxu0DqUTA6Voa3K1d4xFHX2u+UR8AcqR,iv:O0K8i5ivne7WU+ygDEUcrvKW6DIfXjVPY63gpfsxEFE=,tag:n/1atQ5qlyB0SMHrYiTCrA==,type:str]
|
|
||||||
sops:
|
sops:
|
||||||
kms: []
|
kms: []
|
||||||
gcp_kms: []
|
gcp_kms: []
|
||||||
|
@ -98,8 +93,8 @@ sops:
|
||||||
bndBTXJhQVE2OVlKeGNTbzJlL0duUzAKIWdesesYvBIN/m36fhzxq30+IT8qp/pF
|
bndBTXJhQVE2OVlKeGNTbzJlL0duUzAKIWdesesYvBIN/m36fhzxq30+IT8qp/pF
|
||||||
S6i7QqZF75y2BpEoupRCqNIAsHrouUE+U9ZQJZO8m9J591mWvbVJIw==
|
S6i7QqZF75y2BpEoupRCqNIAsHrouUE+U9ZQJZO8m9J591mWvbVJIw==
|
||||||
-----END AGE ENCRYPTED FILE-----
|
-----END AGE ENCRYPTED FILE-----
|
||||||
lastmodified: "2024-07-26T13:05:44Z"
|
lastmodified: "2023-05-03T20:47:22Z"
|
||||||
mac: ENC[AES256_GCM,data:9A8nX155dpCC1cvdH1hgeNKh0tt5FMaOKU7vZQ33jfWbiXOsJbp5iHKXxWOexFc70acyhdweoHwq61oJm2mzVufJIPA55ZAUItQcDXJCCeu6KswHug0tQtKHoCRSwdTdMTRNom4XjrpA/j4WWpuhoilyknycXqTpGHHVSdL2lYg=,iv:N0zwzGtGzAxhbmLzslbkXSr/iKmq5FeyT/iWeE4x2hQ=,tag:yIoLXpqlU2SlVRK5+S/qaw==,type:str]
|
mac: ENC[AES256_GCM,data:5ks4oj4ILLZoJ8TAGLSktV+TZBt1igMOVTiRssr00xnMs1OpR4u0wqwbkM3e2vNP3Hk51AHn7J0W+Ex6f3/iuGdcpYmY/nmSuu+IRZkLL7UEulPm+FDUcw9wgifpNQ263LqvmtFmPURpx4jkTdvcKItWrN0ovV0Wk3jspQ4/QYA=,iv:Kp0cJCYSXBBD4nNetXs6XrFVEl77D7oPuJYAS91DEbU=,tag:b3KF/SFJf1TxDBJ+7KmFvg==,type:str]
|
||||||
pgp: []
|
pgp: []
|
||||||
unencrypted_suffix: _unencrypted
|
unencrypted_suffix: _unencrypted
|
||||||
version: 3.8.1
|
version: 3.7.3
|
||||||
|
|
|
@ -1,16 +1,27 @@
|
||||||
{ config, lib, pkgs, ... }:
|
{ config, lib, pkgs, evalConfig, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
hacc.containers.forgejo = {
|
containers.gitea = {
|
||||||
config = { lib, pkgs, ... }: {
|
privateNetwork = true;
|
||||||
|
hostAddress = "192.168.100.1";
|
||||||
|
localAddress = "192.168.100.10";
|
||||||
|
autoStart = true;
|
||||||
|
bindMounts = {
|
||||||
|
"/persist" = {
|
||||||
|
hostPath = "/persist/containers/gitea";
|
||||||
|
isReadOnly = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
path = evalConfig ({ config, lib, pkgs, ... }: {
|
||||||
system.stateVersion = "21.11";
|
system.stateVersion = "21.11";
|
||||||
|
|
||||||
environment.systemPackages = [ pkgs.forgejo ];
|
environment.systemPackages = [ pkgs.gitea ];
|
||||||
|
|
||||||
hacc.bindMounts."/var/lib/forgejo" = "/persist/forgejo";
|
hexchen.bindmounts."/var/lib/gitea" = "/persist/gitea";
|
||||||
|
|
||||||
services.forgejo = {
|
services.gitea = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
appName = "0x0: git for all creatures";
|
||||||
lfs.enable = true;
|
lfs.enable = true;
|
||||||
database.type = "postgres";
|
database.type = "postgres";
|
||||||
settings = {
|
settings = {
|
||||||
|
@ -54,32 +65,38 @@
|
||||||
log.LEVEL = "Info";
|
log.LEVEL = "Info";
|
||||||
service.DISABLE_REGISTRATION = true;
|
service.DISABLE_REGISTRATION = true;
|
||||||
session.COOKIE_SECURE = true;
|
session.COOKIE_SECURE = true;
|
||||||
default.APP_NAME = "0x0: git for all creatures";
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
services.postgresql.package = pkgs.postgresql_15;
|
|
||||||
|
|
||||||
services.postgresqlBackup = {
|
services.postgresqlBackup = {
|
||||||
enable = true;
|
enable = true;
|
||||||
databases = [ "forgejo" ];
|
databases = [ "gitea" ];
|
||||||
startAt = "*-*-* 23:45:00";
|
startAt = "*-*-* 23:45:00";
|
||||||
location = "/persist/backups/postgres";
|
location = "/persist/backups/postgres";
|
||||||
};
|
};
|
||||||
services.openssh = {
|
services.openssh = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
listenAddresses = [ {
|
||||||
|
addr = "192.168.100.10";
|
||||||
|
port = 22;
|
||||||
|
} ];
|
||||||
settings = {
|
settings = {
|
||||||
PasswordAuthentication = false;
|
PasswordAuthentication = false;
|
||||||
AcceptEnv = "GIT_PROTOCOL";
|
AcceptEnv = "GIT_PROTOCOL";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
services.nginx.virtualHosts."git.infra4future.de" = {
|
services.nginx.virtualHosts."git.infra4future.de" = {
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
enableACME = true;
|
enableACME = true;
|
||||||
locations."/" = {
|
locations."/" = {
|
||||||
proxyPass = "http://${config.containers.forgejo.localAddress}:3000";
|
proxyPass = "http://${config.containers.gitea.localAddress}:3000";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
hexchen.nftables.nat.forwardPorts = [{
|
||||||
|
ports = [ 22 ];
|
||||||
|
destination = "${config.containers.gitea.localAddress}:22";
|
||||||
|
proto = "tcp";
|
||||||
|
}];
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
{ config, lib, pkgs, ... }:
|
{ config, lib, pkgs, evalConfig, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -6,11 +6,19 @@
|
||||||
"hedgedoc-hacc/env" = {};
|
"hedgedoc-hacc/env" = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
containers.pad-hacc.bindMounts = {
|
containers.pad-hacc = {
|
||||||
"/secrets".hostPath = "/run/secrets/hedgedoc-hacc";
|
privateNetwork = true;
|
||||||
};
|
hostAddress = "192.168.100.1";
|
||||||
hacc.containers.pad-hacc = {
|
localAddress = "192.168.100.5";
|
||||||
config = { config, lib, ... }: {
|
autoStart = true;
|
||||||
|
bindMounts = {
|
||||||
|
"/persist" = {
|
||||||
|
hostPath = "/persist/containers/pad-hacc";
|
||||||
|
isReadOnly = false;
|
||||||
|
};
|
||||||
|
"/secrets".hostPath = "/run/secrets/hedgedoc-hacc";
|
||||||
|
};
|
||||||
|
path = evalConfig ({ config, lib, ... }: {
|
||||||
services.hedgedoc = {
|
services.hedgedoc = {
|
||||||
enable = true;
|
enable = true;
|
||||||
settings = {
|
settings = {
|
||||||
|
@ -54,13 +62,15 @@
|
||||||
ensureDatabases = [ "codimd" ];
|
ensureDatabases = [ "codimd" ];
|
||||||
ensureUsers = [{
|
ensureUsers = [{
|
||||||
name = "codimd";
|
name = "codimd";
|
||||||
ensureDBOwnership = true;
|
ensurePermissions = {
|
||||||
|
"DATABASE codimd" = "ALL PRIVILEGES";
|
||||||
|
};
|
||||||
}];
|
}];
|
||||||
authentication = ''
|
authentication = ''
|
||||||
local all all trust
|
local all all trust
|
||||||
host codimd codimd 127.0.0.1/32 trust
|
host codimd codimd 127.0.0.1/32 trust
|
||||||
'';
|
'';
|
||||||
package = pkgs.postgresql_15;
|
package = pkgs.postgresql_11;
|
||||||
};
|
};
|
||||||
services.postgresqlBackup = {
|
services.postgresqlBackup = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
@ -68,8 +78,7 @@
|
||||||
startAt = "*-*-* 23:45:00";
|
startAt = "*-*-* 23:45:00";
|
||||||
location = "/persist/backups/postgres";
|
location = "/persist/backups/postgres";
|
||||||
};
|
};
|
||||||
hacc.bindToPersist = [ "/var/lib/hedgedoc" ];
|
});
|
||||||
};
|
|
||||||
};
|
};
|
||||||
services.nginx.virtualHosts."pad.hacc.earth" = {
|
services.nginx.virtualHosts."pad.hacc.earth" = {
|
||||||
enableACME = true;
|
enableACME = true;
|
|
@ -1,8 +1,18 @@
|
||||||
{ config, lib, pkgs, ... }:
|
{ config, lib, pkgs, evalConfig, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
hacc.containers.pad-i4f = {
|
containers.pad-i4f = {
|
||||||
config = { config, lib, ... }: {
|
privateNetwork = true;
|
||||||
|
hostAddress = "192.168.100.1";
|
||||||
|
localAddress = "192.168.100.6";
|
||||||
|
autoStart = true;
|
||||||
|
bindMounts = {
|
||||||
|
"/persist" = {
|
||||||
|
hostPath = "/persist/containers/pad-i4f";
|
||||||
|
isReadOnly = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
path = evalConfig ({ config, lib, ... }: {
|
||||||
services.hedgedoc = {
|
services.hedgedoc = {
|
||||||
enable = true;
|
enable = true;
|
||||||
settings = {
|
settings = {
|
||||||
|
@ -28,7 +38,7 @@
|
||||||
};
|
};
|
||||||
services.postgresql = {
|
services.postgresql = {
|
||||||
enable = true;
|
enable = true;
|
||||||
package = pkgs.postgresql_15;
|
package = pkgs.postgresql_11;
|
||||||
authentication = ''
|
authentication = ''
|
||||||
local all all trust
|
local all all trust
|
||||||
host hedgedoc hedgedoc 127.0.0.1/32 trust
|
host hedgedoc hedgedoc 127.0.0.1/32 trust
|
||||||
|
@ -36,7 +46,9 @@
|
||||||
ensureDatabases = [ "hedgedoc" ];
|
ensureDatabases = [ "hedgedoc" ];
|
||||||
ensureUsers = [{
|
ensureUsers = [{
|
||||||
name = "hedgedoc";
|
name = "hedgedoc";
|
||||||
ensureDBOwnership = true;
|
ensurePermissions = {
|
||||||
|
"DATABASE hedgedoc" = "ALL PRIVILEGES";
|
||||||
|
};
|
||||||
}];
|
}];
|
||||||
};
|
};
|
||||||
services.postgresqlBackup = {
|
services.postgresqlBackup = {
|
||||||
|
@ -45,8 +57,7 @@
|
||||||
startAt = "*-*-* 23:45:00";
|
startAt = "*-*-* 23:45:00";
|
||||||
location = "/persist/backups/postgres";
|
location = "/persist/backups/postgres";
|
||||||
};
|
};
|
||||||
hacc.bindToPersist = [ "/var/lib/hedgedoc" ];
|
});
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
services.nginx.virtualHosts."pad.infra4future.de" = {
|
services.nginx.virtualHosts."pad.infra4future.de" = {
|
|
@ -1,4 +1,4 @@
|
||||||
{ config, options, pkgs, lib, sources, ... }:
|
{ config, pkgs, lib, sources, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
imports = [ sources.nixos-mailserver.outPath ];
|
imports = [ sources.nixos-mailserver.outPath ];
|
||||||
|
@ -187,22 +187,11 @@
|
||||||
bindIP = "[::1]";
|
bindIP = "[::1]";
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.services.alps.after = [ "dovecot2.service" "postfix.service" ];
|
systemd.services.alps.after = [ "dovecot2.service" ];
|
||||||
systemd.services.alps.bindsTo = [ "dovecot2.service" "postfix.service" ];
|
|
||||||
|
|
||||||
services.nginx.virtualHosts."mail.hacc.space" = {
|
services.nginx.virtualHosts."mail.hacc.space" = {
|
||||||
enableACME = true;
|
enableACME = true;
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
locations."/".proxyPass = "http://[::1]:1323";
|
locations."/".proxyPass = "http://[::1]:1323";
|
||||||
};
|
};
|
||||||
|
|
||||||
hacc.bindToPersist = [
|
|
||||||
"/var/lib/rspamd"
|
|
||||||
"/var/lib/opendkim"
|
|
||||||
"/var/lib/postfix"
|
|
||||||
"/var/lib/dovecot"
|
|
||||||
"/var/sieve"
|
|
||||||
"/var/lib/redis-rspamd"
|
|
||||||
"/var/dkim"
|
|
||||||
];
|
|
||||||
}
|
}
|
|
@ -1,16 +1,25 @@
|
||||||
{ config, pkgs, lib, ...}:
|
{ config, pkgs, lib, evalConfig, ...}:
|
||||||
|
|
||||||
{
|
{
|
||||||
sops.secrets = {
|
sops.secrets = {
|
||||||
"mattermost/env" = {};
|
"mattermost/env" = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
hacc.containers.mattermost = {
|
containers.mattermost = {
|
||||||
bindSecrets = true;
|
autoStart = true;
|
||||||
|
privateNetwork = true;
|
||||||
|
hostAddress = "192.168.100.1";
|
||||||
|
localAddress = "192.168.100.3";
|
||||||
|
|
||||||
config = { config, lib, pkgs, ... }: {
|
bindMounts = {
|
||||||
environment.systemPackages = [ pkgs.morph pkgs.pgloader ];
|
"/persist" = {
|
||||||
|
hostPath = "/persist/containers/mattermost";
|
||||||
|
isReadOnly = false;
|
||||||
|
};
|
||||||
|
"/secrets".hostPath = "/run/secrets/mattermost";
|
||||||
|
};
|
||||||
|
|
||||||
|
path = evalConfig ({ config, lib, pkgs, ... }: {
|
||||||
systemd.services.mattermost.serviceConfig.EnvironmentFile =
|
systemd.services.mattermost.serviceConfig.EnvironmentFile =
|
||||||
lib.mkForce "/secrets/env";
|
lib.mkForce "/secrets/env";
|
||||||
|
|
||||||
|
@ -62,6 +71,8 @@
|
||||||
};
|
};
|
||||||
LogSettings = {
|
LogSettings = {
|
||||||
EnableConsole = true;
|
EnableConsole = true;
|
||||||
|
# note: for some reason this doesn't work (mattermost still sets it to DEBUG);
|
||||||
|
# it's also set in secrets.env, where for some reason it does
|
||||||
ConsoleLevel = "ERROR";
|
ConsoleLevel = "ERROR";
|
||||||
EnableDiagnostics = false;
|
EnableDiagnostics = false;
|
||||||
EnableWebhookDebugging = false;
|
EnableWebhookDebugging = false;
|
||||||
|
@ -144,12 +155,18 @@
|
||||||
Enable = true;
|
Enable = true;
|
||||||
EnableUploads = true;
|
EnableUploads = true;
|
||||||
Plugins = {
|
Plugins = {
|
||||||
|
bigbluebutton = {
|
||||||
|
adminonly = false;
|
||||||
|
base_url = "https://bbb.infra4future.de/bigbluebutton/api";
|
||||||
|
salt = "zKCsNeaEniC115ynHOsZopgA4iTiJjzgeiPNoCEc";
|
||||||
|
};
|
||||||
"com.github.matterpoll.matterpoll" = {
|
"com.github.matterpoll.matterpoll" = {
|
||||||
experimentalui = true;
|
experimentalui = true;
|
||||||
trigger = "poll";
|
trigger = "poll";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
PluginStates = {
|
PluginStates = {
|
||||||
|
bigbluebutton.Enable = true;
|
||||||
"com.github.matterpoll.matterpoll".Enable = true;
|
"com.github.matterpoll.matterpoll".Enable = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -158,8 +175,6 @@
|
||||||
MetricsSettings.Enable = false;
|
MetricsSettings.Enable = false;
|
||||||
GuestAccountsSettings.Enable = false;
|
GuestAccountsSettings.Enable = false;
|
||||||
FeatureFlags.CollapsedThreads = true;
|
FeatureFlags.CollapsedThreads = true;
|
||||||
SqlSettings.DriverName = "postgres";
|
|
||||||
SqlSettings.DataSource = "postgres:///mattermost?host=/run/postgresql";
|
|
||||||
};
|
};
|
||||||
|
|
||||||
# turn of the weirder parts of this module (which insist on passwords
|
# turn of the weirder parts of this module (which insist on passwords
|
||||||
|
@ -170,28 +185,36 @@
|
||||||
localDatabaseCreate = false;
|
localDatabaseCreate = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
services.postgresql = {
|
services.mysql = {
|
||||||
enable = lib.mkForce true; # mattermost sets this to false. wtf.
|
enable = true;
|
||||||
package = pkgs.postgresql_15;
|
|
||||||
ensureDatabases = [ "mattermost" ];
|
ensureDatabases = [ "mattermost" ];
|
||||||
ensureUsers = [ {
|
ensureUsers = [ {
|
||||||
name = "mattermost";
|
name = "mattermost";
|
||||||
ensureDBOwnership = true;
|
ensurePermissions = { "mattermost.*" = "ALL PRIVILEGES"; };
|
||||||
|
} ];
|
||||||
|
package = pkgs.mysql80;
|
||||||
|
dataDir = "/persist/mysql";
|
||||||
|
};
|
||||||
|
|
||||||
|
services.postgresql = {
|
||||||
|
enable = lib.mkForce true; # mattermost sets this to false. wtf.
|
||||||
|
package = pkgs.postgresql_11;
|
||||||
|
ensureDatabases = [ "mattermost" ];
|
||||||
|
ensureUsers = [ {
|
||||||
|
name = "mattermost";
|
||||||
|
ensurePermissions = { "DATABASE mattermost" = "ALL PRIVILEGES"; };
|
||||||
} ];
|
} ];
|
||||||
|
|
||||||
authentication = lib.mkForce ''
|
authentication = lib.mkForce ''
|
||||||
# Generated file; do not edit!
|
# Generated file; do not edit!
|
||||||
local all all trust
|
local all all trust
|
||||||
|
host mattermost mattermost ::1/128 trust
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
services.postgresqlBackup = {
|
networking.firewall.allowedTCPPorts = [ 3000 ];
|
||||||
enable = true;
|
|
||||||
databases = [ "mattermost" ];
|
});
|
||||||
startAt = "*-*-* 23:45:00";
|
|
||||||
location = "/persist/backups/postgres";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
services.nginx.virtualHosts."mattermost.infra4future.de" = {
|
services.nginx.virtualHosts."mattermost.infra4future.de" = {
|
|
@ -1,13 +1,13 @@
|
||||||
{ config, lib, pkgs, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
|
hexchen.bindmounts."/var/lib/murmur" = "/persist/var/lib/murmur";
|
||||||
|
|
||||||
services.murmur = {
|
services.murmur = {
|
||||||
enable = true;
|
enable = true;
|
||||||
logDays = -1;
|
logDays = -1;
|
||||||
registerName = "hackers against climate change";
|
welcometext =
|
||||||
welcometext = ''
|
"Welcome to mumble4future! Brought to you by infra4future. The server is now reachable under mumble.hacc.space, please update your bookmarks.";
|
||||||
<br>Welcome to <b>mumble4future</b>!<br>Brought to you by <b style="color:red">infra4future</b>.<br>On <a href=https://mumble.hacc.space>mumble.hacc.space</a><br>Not confusing at all!
|
|
||||||
'';
|
|
||||||
sslKey = "/var/lib/acme/mumble.hacc.space/key.pem";
|
sslKey = "/var/lib/acme/mumble.hacc.space/key.pem";
|
||||||
sslCert = "/var/lib/acme/mumble.hacc.space/fullchain.pem";
|
sslCert = "/var/lib/acme/mumble.hacc.space/fullchain.pem";
|
||||||
bandwidth = 128000;
|
bandwidth = 128000;
|
||||||
|
@ -25,6 +25,4 @@
|
||||||
};
|
};
|
||||||
users.users.nginx.extraGroups = [ "mumblecert" ];
|
users.users.nginx.extraGroups = [ "mumblecert" ];
|
||||||
users.users.murmur.extraGroups = [ "mumblecert" ];
|
users.users.murmur.extraGroups = [ "mumblecert" ];
|
||||||
|
|
||||||
hacc.bindToPersist = [ "/var/lib/murmur" ];
|
|
||||||
}
|
}
|
|
@ -1,9 +1,18 @@
|
||||||
{ config, lib, pkgs, ... }:
|
{ config, lib, pkgs, evalConfig, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
containers.nextcloud.timeoutStartSec = "10 min";
|
containers.nextcloud = {
|
||||||
hacc.containers.nextcloud = {
|
autoStart = true;
|
||||||
config = { config, lib, pkgs, ... }: {
|
privateNetwork = true;
|
||||||
|
hostAddress = "192.168.100.1";
|
||||||
|
localAddress = "192.168.100.2";
|
||||||
|
bindMounts = {
|
||||||
|
"/persist" = {
|
||||||
|
hostPath = "/persist/containers/nextcloud";
|
||||||
|
isReadOnly = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
path = evalConfig ({ config, lib, pkgs, ... }: {
|
||||||
environment.systemPackages = [ pkgs.htop ];
|
environment.systemPackages = [ pkgs.htop ];
|
||||||
|
|
||||||
services.nextcloud = {
|
services.nextcloud = {
|
||||||
|
@ -11,11 +20,14 @@
|
||||||
|
|
||||||
# must be set manually; may not be incremented by more than one at
|
# must be set manually; may not be incremented by more than one at
|
||||||
# a time, otherwise nextcloud WILL break
|
# a time, otherwise nextcloud WILL break
|
||||||
package = pkgs.nextcloud29;
|
package = pkgs.nextcloud27;
|
||||||
|
|
||||||
home = "/persist/nextcloud";
|
home = "/persist/nextcloud";
|
||||||
https = true;
|
https = true;
|
||||||
|
|
||||||
|
# true by default for backwards-compatability, but we don't need it
|
||||||
|
enableBrokenCiphersForSSE = false;
|
||||||
|
|
||||||
hostName = "cloud.infra4future.de";
|
hostName = "cloud.infra4future.de";
|
||||||
config = {
|
config = {
|
||||||
dbtype = "pgsql";
|
dbtype = "pgsql";
|
||||||
|
@ -39,7 +51,7 @@
|
||||||
"pm.start_servers" = "2";
|
"pm.start_servers" = "2";
|
||||||
};
|
};
|
||||||
|
|
||||||
settings = {
|
extraOptions = {
|
||||||
instanceid = "ocxlphb7fbju";
|
instanceid = "ocxlphb7fbju";
|
||||||
datadirectory = "/persist/nextcloud/data";
|
datadirectory = "/persist/nextcloud/data";
|
||||||
loglevel = 0;
|
loglevel = 0;
|
||||||
|
@ -49,30 +61,23 @@
|
||||||
|
|
||||||
services.postgresql = {
|
services.postgresql = {
|
||||||
enable = true;
|
enable = true;
|
||||||
package = pkgs.postgresql_15;
|
package = pkgs.postgresql_11;
|
||||||
ensureDatabases = [ "nextcloud" ];
|
ensureDatabases = [ "nextcloud" ];
|
||||||
ensureUsers = [
|
ensureUsers = [
|
||||||
{ # by default, postgres has unix sockets enabled, and allows a
|
{ # by default, postgres has unix sockets enabled, and allows a
|
||||||
# system user `nextcloud` to log in without other authentication
|
# system user `nextcloud` to log in without other authentication
|
||||||
name = "nextcloud";
|
name = "nextcloud";
|
||||||
ensureDBOwnership = true;
|
ensurePermissions."DATABASE nextcloud" = "ALL PRIVILEGES";
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
services.postgresqlBackup = {
|
|
||||||
enable = true;
|
|
||||||
databases = [ "nextcloud" ];
|
|
||||||
startAt = "*-*-* 23:45:00";
|
|
||||||
location = "/persist/backups/postgres";
|
|
||||||
};
|
|
||||||
|
|
||||||
# ensure that postgres is running *before* running the setup
|
# ensure that postgres is running *before* running the setup
|
||||||
systemd.services."nextcloud-setup" = {
|
systemd.services."nextcloud-setup" = {
|
||||||
requires = ["postgresql.service"];
|
requires = ["postgresql.service"];
|
||||||
after = ["postgresql.service"];
|
after = ["postgresql.service"];
|
||||||
};
|
};
|
||||||
};
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
services.nginx.virtualHosts."cloud.infra4future.de" = {
|
services.nginx.virtualHosts."cloud.infra4future.de" = {
|
9
services/nginx-pages.nix
Normal file
9
services/nginx-pages.nix
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
{ config, pkgs, ... }:
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
hacc.websites = {
|
||||||
|
enable = true;
|
||||||
|
directory = ../websites;
|
||||||
|
};
|
||||||
|
}
|
52
services/onlyoffice.nix
Normal file
52
services/onlyoffice.nix
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
{ config, lib, pkgs, evalConfig, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
containers.onlyoffice = {
|
||||||
|
privateNetwork = true;
|
||||||
|
hostAddress = "192.168.142.1";
|
||||||
|
localAddress = "192.168.142.10";
|
||||||
|
autoStart = true;
|
||||||
|
bindMounts = {
|
||||||
|
"/persist" = {
|
||||||
|
hostPath = "/persist/containers/onlyoffice";
|
||||||
|
isReadOnly = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
extraFlags = [ "--system-call-filter=proc_create_mount_point" ];
|
||||||
|
path = evalConfig ({ config, lib, pkgs, ... }: {
|
||||||
|
system.stateVersion = "21.11";
|
||||||
|
|
||||||
|
services.postgresql = {
|
||||||
|
enable = true;
|
||||||
|
|
||||||
|
ensureDatabases = [ "onlyoffice" ];
|
||||||
|
ensureUsers = [ {
|
||||||
|
name = "onlyoffice";
|
||||||
|
ensurePermissions = {
|
||||||
|
"DATABASE onlyoffice" = "ALL PRIVILEGES";
|
||||||
|
};
|
||||||
|
} ];
|
||||||
|
authentication = ''
|
||||||
|
local all all trust
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
services.rabbitmq = {
|
||||||
|
enable = true;
|
||||||
|
dataDir = "/persist/rabbitmq";
|
||||||
|
};
|
||||||
|
|
||||||
|
services.onlyoffice = {
|
||||||
|
enable = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.firewall.allowedTCPPorts = [ 8000 ];
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
services.nginx.virtualHosts."onlyoffice-staging.infra4future.de" = {
|
||||||
|
enableACME = true;
|
||||||
|
forceSSL = true;
|
||||||
|
locations."/".proxyPass = "http://${config.containers.onlyoffice.localAddress}:8000";
|
||||||
|
};
|
||||||
|
}
|
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;
|
||||||
|
};
|
||||||
|
}
|
156
services/tracktrain.nix
Normal file
156
services/tracktrain.nix
Normal file
|
@ -0,0 +1,156 @@
|
||||||
|
{ config, lib, pkgs, evalConfig, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
tracktrain-config = ''
|
||||||
|
dbstring: "dbname=tracktrain"
|
||||||
|
gtfs: /persist/gtfs.zip
|
||||||
|
assets: ${pkgs.tracktrain}/assets
|
||||||
|
|
||||||
|
warp:
|
||||||
|
port: 4000
|
||||||
|
|
||||||
|
login:
|
||||||
|
enable: true
|
||||||
|
url: https://login.infra4future.de
|
||||||
|
clientname: tracktrain
|
||||||
|
# clientsecret defined in env file
|
||||||
|
'';
|
||||||
|
in
|
||||||
|
{
|
||||||
|
sops.secrets = {
|
||||||
|
"tracktrain/env" = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
services.nginx.virtualHosts."tracktrain.ilztalbahn.eu" = {
|
||||||
|
enableACME = true;
|
||||||
|
forceSSL = true;
|
||||||
|
locations."/" = {
|
||||||
|
proxyPass = "http://192.168.42.41:4000";
|
||||||
|
proxyWebsockets = true;
|
||||||
|
};
|
||||||
|
# note: this shadows the /metrics endpoint of tracktrain
|
||||||
|
# in case you remove this, please consider putting something
|
||||||
|
# else here to keep it from being publicly scrapable
|
||||||
|
locations."/metrics/" = {
|
||||||
|
proxyPass = "http://192.168.42.41:2342";
|
||||||
|
proxyWebsockets = true;
|
||||||
|
extraConfig = ''
|
||||||
|
rewrite ^/metrics/(.*) /$1 break;
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
containers.tracktrain = {
|
||||||
|
privateNetwork = true;
|
||||||
|
hostAddress = "192.168.42.40";
|
||||||
|
localAddress = "192.168.42.41";
|
||||||
|
autoStart = true;
|
||||||
|
bindMounts = {
|
||||||
|
"/persist" = {
|
||||||
|
hostPath = "/persist/containers/tracktrain";
|
||||||
|
isReadOnly = false;
|
||||||
|
};
|
||||||
|
"/secrets".hostPath = "/run/secrets/tracktrain";
|
||||||
|
};
|
||||||
|
|
||||||
|
path = evalConfig ({ config, lib, pkgs, ... }: {
|
||||||
|
system.stateVersion = "21.11";
|
||||||
|
|
||||||
|
users.users.tracktrain = {
|
||||||
|
group = "tracktrain";
|
||||||
|
isSystemUser = true;
|
||||||
|
};
|
||||||
|
users.groups.tracktrain = {};
|
||||||
|
|
||||||
|
systemd.services.tracktrain = {
|
||||||
|
enable = true;
|
||||||
|
|
||||||
|
description = "tracks trains, hopefully";
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
requires = [ "network.target" ];
|
||||||
|
after = [ "network.target" ];
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "simple";
|
||||||
|
EnvironmentFile = "/secrets/env";
|
||||||
|
User = "tracktrain";
|
||||||
|
Group = "tracktrain";
|
||||||
|
};
|
||||||
|
path = [ pkgs.wget ];
|
||||||
|
script = ''
|
||||||
|
mkdir -p /persist/tracktrain
|
||||||
|
cd /persist/tracktrain
|
||||||
|
ln -sf ${pkgs.writeText "tracktrain-config.yaml" tracktrain-config} config.yaml
|
||||||
|
wget "https://ilztalbahn.eu/wp-content/uploads/2020/07/gtfs.zip" || sleep 4; wget "https://ilztalbahn.eu/wp-content/uploads/2020/07/gtfs.zip"
|
||||||
|
${pkgs.tracktrain}/bin/tracktrain +RTS -T
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
services.postgresql = {
|
||||||
|
enable = true;
|
||||||
|
|
||||||
|
ensureDatabases = [ "tracktrain" ];
|
||||||
|
ensureUsers = [ {
|
||||||
|
name = "tracktrain";
|
||||||
|
ensurePermissions = {
|
||||||
|
"DATABASE tracktrain" = "ALL PRIVILEGES";
|
||||||
|
};
|
||||||
|
} ];
|
||||||
|
authentication = ''
|
||||||
|
local all all trust
|
||||||
|
host all all 127.0.0.1/32 trust
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
services.prometheus = {
|
||||||
|
enable = true;
|
||||||
|
port = 9001;
|
||||||
|
scrapeConfigs = [ {
|
||||||
|
job_name = "tracktrain";
|
||||||
|
static_configs = [{
|
||||||
|
targets = [ "0.0.0.0:4000" ];
|
||||||
|
}];
|
||||||
|
} ];
|
||||||
|
};
|
||||||
|
|
||||||
|
services.grafana = {
|
||||||
|
enable = true;
|
||||||
|
settings.server = {
|
||||||
|
serve_from_sub_path = true;
|
||||||
|
domain = "tracktrain.ilztalbahn.eu";
|
||||||
|
root_url = "https://%(domain)s/metrics/";
|
||||||
|
http_port = 2342;
|
||||||
|
http_addr = "0.0.0.0";
|
||||||
|
};
|
||||||
|
|
||||||
|
settings."auth.generic_oauth" = {
|
||||||
|
name = "uffd";
|
||||||
|
enabled = true;
|
||||||
|
allow_sign_up = true;
|
||||||
|
empty_scopes = true;
|
||||||
|
client_id = "ilztalbahn-grafana";
|
||||||
|
client_secret = "\${GRAFANA_CLIENT_SECRET}";
|
||||||
|
auth_url = "https://login.infra4future.de/oauth2/authorize";
|
||||||
|
token_url = "https://login.infra4future.de/oauth2/token";
|
||||||
|
api_url = "https://login.infra4future.de/oauth2/userinfo";
|
||||||
|
};
|
||||||
|
# disables the default login screen. comment out if for some
|
||||||
|
# reason you do need it
|
||||||
|
settings.auth.oauth_auto_login = true;
|
||||||
|
settings.users.auto_assign_org_role = "Admin";
|
||||||
|
|
||||||
|
provision = {
|
||||||
|
enable = true;
|
||||||
|
datasources.settings.datasources = [ {
|
||||||
|
url = "http://localhost:9001";
|
||||||
|
type = "prometheus";
|
||||||
|
name = "prometheus";
|
||||||
|
} ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.grafana.serviceConfig.EnvironmentFile =
|
||||||
|
"/secrets/env";
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -1,8 +1,18 @@
|
||||||
{ config, lib, pkgs, ... }:
|
{ config, lib, pkgs, evalConfig, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
hacc.containers.uffd = {
|
containers.uffd = {
|
||||||
config = { config, lib, pkgs, ... }: {
|
privateNetwork = true;
|
||||||
|
hostAddress = "192.168.100.1";
|
||||||
|
localAddress = "192.168.100.9";
|
||||||
|
autoStart = true;
|
||||||
|
bindMounts = {
|
||||||
|
"/persist" = {
|
||||||
|
hostPath = "/persist/containers/uffd";
|
||||||
|
isReadOnly = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
path = evalConfig ({ config, lib, pkgs, ... }: {
|
||||||
services.uwsgi = {
|
services.uwsgi = {
|
||||||
enable = true;
|
enable = true;
|
||||||
plugins = [ "python3" ];
|
plugins = [ "python3" ];
|
||||||
|
@ -18,7 +28,7 @@
|
||||||
hook-pre-app = "exec:FLASK_APP=${pkgs.uffd}/lib/python3.10/site-packages/uffd flask db upgrade";
|
hook-pre-app = "exec:FLASK_APP=${pkgs.uffd}/lib/python3.10/site-packages/uffd flask db upgrade";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
});
|
||||||
};
|
};
|
||||||
services.nginx.virtualHosts."login.infra4future.de" = {
|
services.nginx.virtualHosts."login.infra4future.de" = {
|
||||||
enableACME = true;
|
enableACME = true;
|
||||||
|
@ -43,24 +53,9 @@
|
||||||
after = [ "network.target" ];
|
after = [ "network.target" ];
|
||||||
serviceConfig.Type = "simple";
|
serviceConfig.Type = "simple";
|
||||||
path = [ pkgs.fish pkgs.curl pkgs.jq ];
|
path = [ pkgs.fish pkgs.curl pkgs.jq ];
|
||||||
script = "${pkgs.hacc-scripts}/bin/uffd-sync-mattermost-groups.fish";
|
script = "/persist/magic/mattermost-groupsync.fish";
|
||||||
startAt = "*:0/15";
|
startAt = "*:0/15";
|
||||||
};
|
};
|
||||||
|
|
||||||
systemd.services.uffd-account-expiry-notification = {
|
|
||||||
enable = true;
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
after = [ "network.target" ];
|
|
||||||
serviceConfig.Type = "simple";
|
|
||||||
path = [ pkgs.hacc-scripts pkgs.sqlite-interactive pkgs.postfix ];
|
|
||||||
script = ''
|
|
||||||
uffd-unused-accounts-notification.scm -v admin
|
|
||||||
'';
|
|
||||||
startAt = "weekly";
|
|
||||||
restartIfChanged = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
sops.secrets."auamost/secrets.fish" = { };
|
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; [ curl jq ];
|
environment.systemPackages = with pkgs; [ curl jq ];
|
||||||
}
|
}
|
|
@ -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,22 +0,0 @@
|
||||||
{ copyPathToStore, stdenvNoCC, zola, writeShellScriptBin }:
|
|
||||||
|
|
||||||
stdenvNoCC.mkDerivation rec {
|
|
||||||
name = "docs.hacc.space-static";
|
|
||||||
|
|
||||||
src = ./.;
|
|
||||||
content = copyPathToStore ../../docs;
|
|
||||||
|
|
||||||
phases = [ "buildPhase" ];
|
|
||||||
buildInputs = [ zola ];
|
|
||||||
buildPhase = ''
|
|
||||||
cp -r $src/* .
|
|
||||||
rm content
|
|
||||||
ln -s $content content
|
|
||||||
zola build --output-dir $out
|
|
||||||
'';
|
|
||||||
|
|
||||||
watch = writeShellScriptBin "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 %}
|
|
|
@ -1,4 +1,4 @@
|
||||||
{ stdenvNoCC, sfz, writeShellScriptBin }:
|
{ stdenvNoCC, sfz, writeScriptBin }:
|
||||||
|
|
||||||
stdenvNoCC.mkDerivation rec {
|
stdenvNoCC.mkDerivation rec {
|
||||||
name = "hacc.earth-static";
|
name = "hacc.earth-static";
|
||||||
|
@ -13,8 +13,7 @@ stdenvNoCC.mkDerivation rec {
|
||||||
rm $out/default.nix
|
rm $out/default.nix
|
||||||
'';
|
'';
|
||||||
|
|
||||||
watch = writeShellScriptBin "watch" ''
|
watch = writeScriptBin "watch" ''
|
||||||
cd $(git rev-parse --show-toplevel)/websites/hacc.earth
|
${sfz}/bin/sfz -r ${src} "$@"
|
||||||
${sfz}/bin/sfz "$@"
|
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|
|
@ -270,7 +270,7 @@
|
||||||
<a href="https://muc.hacc.earth">hacc e.V.</a>, local chapter Munich<sup><a href="#history">*</a></sup>
|
<a href="https://muc.hacc.earth">hacc e.V.</a>, local chapter Munich<sup><a href="#history">*</a></sup>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<a href="https://webirc.hackint.org/#ircs://irc.hackint.org/#hacc-muc">#hacc-muc</a> on hackint.org or as matrix bridge <a href="https://matrix.to/#/#hacc-muc:hackint.org">#hacc-muc:hackint.org</a>
|
<del><a href="https://webirc.hackint.org/#ircs://irc.hackint.org/#hacc-muc">#hacc-muc</a> on hackint.org or as matrix bridge <a href="https://matrix.to/#/#hacc-muc:hackint.org">#hacc-muc:hackint.org</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="https://chaos.social/@hacc">@hacc@chaos.social</a>
|
<a href="https://chaos.social/@hacc">@hacc@chaos.social</a>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{ stdenvNoCC, sfz, writeShellScriptBin }:
|
{ stdenvNoCC, sfz, writeScriptBin }:
|
||||||
|
|
||||||
stdenvNoCC.mkDerivation rec {
|
stdenvNoCC.mkDerivation rec {
|
||||||
name = "muc.hacc.earth-static";
|
name = "muc.hacc.earth-static";
|
||||||
|
@ -13,8 +13,7 @@ stdenvNoCC.mkDerivation rec {
|
||||||
rm $out/default.nix
|
rm $out/default.nix
|
||||||
'';
|
'';
|
||||||
|
|
||||||
watch = writeShellScriptBin "watch" ''
|
watch = writeScriptBin "watch" ''
|
||||||
cd $(git rev-parse --show-toplevel)/websites/help.studentsforfuture.info
|
${sfz}/bin/sfz -r ${src}
|
||||||
${sfz}/bin/sfz "$@"
|
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{ jekyll, stdenvNoCC, writeShellScriptBin }:
|
{ jekyll, stdenvNoCC, writeScriptBin }:
|
||||||
|
|
||||||
stdenvNoCC.mkDerivation rec {
|
stdenvNoCC.mkDerivation rec {
|
||||||
name = "infra4future.de-static";
|
name = "infra4future.de-static";
|
||||||
|
@ -11,9 +11,8 @@ stdenvNoCC.mkDerivation rec {
|
||||||
${jekyll}/bin/jekyll build -d $out --disable-disk-cache
|
${jekyll}/bin/jekyll build -d $out --disable-disk-cache
|
||||||
'';
|
'';
|
||||||
|
|
||||||
watch = writeShellScriptBin "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
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{ stdenvNoCC, sfz, writeShellScriptBin }:
|
{ stdenvNoCC, sfz, writeScriptBin }:
|
||||||
|
|
||||||
stdenvNoCC.mkDerivation rec {
|
stdenvNoCC.mkDerivation rec {
|
||||||
name = "muc.hacc.earth-static";
|
name = "muc.hacc.earth-static";
|
||||||
|
@ -13,8 +13,7 @@ stdenvNoCC.mkDerivation rec {
|
||||||
rm $out/default.nix
|
rm $out/default.nix
|
||||||
'';
|
'';
|
||||||
|
|
||||||
watch = writeShellScriptBin "watch" ''
|
watch = writeScriptBin "watch" ''
|
||||||
cd $(git rev-parse --show-toplevel)/websites/muc.hacc.earth
|
${sfz}/bin/sfz -r ${src}
|
||||||
${sfz}/bin/sfz "$@"
|
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{ jekyll, stdenvNoCC, writeShellScriptBin }:
|
{ jekyll, stdenvNoCC, writeScriptBin }:
|
||||||
|
|
||||||
stdenvNoCC.mkDerivation rec {
|
stdenvNoCC.mkDerivation rec {
|
||||||
name = "mumble.infra4future.de-static";
|
name = "mumble.infra4future.de-static";
|
||||||
|
@ -11,9 +11,8 @@ stdenvNoCC.mkDerivation rec {
|
||||||
${jekyll}/bin/jekyll build -d $out --disable-disk-cache
|
${jekyll}/bin/jekyll build -d $out --disable-disk-cache
|
||||||
'';
|
'';
|
||||||
|
|
||||||
watch = writeShellScriptBin "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