Switch over to nix flakes and introduce podman pods #26
1
.gitattributes
vendored
1
.gitattributes
vendored
|
@ -1 +0,0 @@
|
|||
*.tar.gz filter=lfs diff=lfs merge=lfs -text
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,2 +1,2 @@
|
|||
/result
|
||||
/tlater.net.qcow2
|
||||
/tlaternet.qcow2
|
||||
|
|
11
Makefile
11
Makefile
|
@ -1,11 +0,0 @@
|
|||
result: etc/nixos/configuration.nix
|
||||
nix-build '<nixpkgs/nixos>' -A vm -k -I nixos-config=$^
|
||||
|
||||
tlaternet.qcow2:
|
||||
nix-shell -p qemu --run 'qemu-img create -f qcow2 $@ 10G'
|
||||
|
||||
run: result tlaternet.qcow2
|
||||
QEMU_OPTS="-m 4096 -nographic" QEMU_NET_OPTS="hostfwd=tcp::2222-:2222,hostfwd=tcp::8000-:80,hostfwd=tcp::25565-:25565" ./result/bin/run-tlaternet-vm
|
||||
|
||||
format: $(wildcard etc/nixos/**/*.nix)
|
||||
nix-shell -p nixpkgs-fmt --run 'nixpkgs-fmt $^'
|
55
README.md
55
README.md
|
@ -6,51 +6,30 @@ This is the NixOS configuration for [tlater.net](https://tlater.net/).
|
|||
|
||||
### Building
|
||||
|
||||
To test locally in a VM, [nix](https://nixos.org/nix/) is
|
||||
required. Using a properly-configured nix, a qemu-based VM running the
|
||||
server can be created by first applying the following patch to disable
|
||||
hardware-specific configuration:
|
||||
|
||||
```patch
|
||||
diff --git a/etc/nixos/configuration.nix b/etc/nixos/configuration.nix
|
||||
index 387113d..aabee88 100644
|
||||
--- a/etc/nixos/configuration.nix
|
||||
+++ b/etc/nixos/configuration.nix
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
{
|
||||
imports = [
|
||||
- ./hardware-configuration.nix
|
||||
- ./linode.nix
|
||||
+ # ./hardware-configuration.nix
|
||||
+ # ./linode.nix
|
||||
];
|
||||
|
||||
networking = {
|
||||
```
|
||||
|
||||
Then building the VM with:
|
||||
Build the VM with:
|
||||
|
||||
```
|
||||
nix-build '<nixpkgs/nixos>' -A vm -k -I nixos-config=./configuration.nix
|
||||
nixos-rebuild build-vm --flake '.#vm'
|
||||
```
|
||||
|
||||
### Running
|
||||
|
||||
To invoke the VM, use:
|
||||
Running should *mostly* be as simple as running the command the build
|
||||
script echos.
|
||||
|
||||
```
|
||||
QEMU_NET_OPTS="hostfwd=tcp::2222-:2222,hostfwd=tcp::8000-:80" ./result/bin/run-tlater.net-vm
|
||||
One caveat: create a larger disk image first. This can be done by
|
||||
running the following in the repository root:
|
||||
|
||||
```bash
|
||||
qemu-img create -f qcow2 ./tlaternet.qcow2 20G
|
||||
```
|
||||
|
||||
This will set up a qemu VM with ports 2222 linked to the ssh port, and
|
||||
8000 to the http port. If other ports are required, adjust the
|
||||
environment variable (notably, ssl is provided by the image, although
|
||||
it should not work since it is unlikely that letsencrypt will supply
|
||||
any certificates).
|
||||
Everything else should be handled by the devShell.
|
||||
|
||||
Note that other environment variables are available (such as one for
|
||||
disabling the qt GUI, probably handy for eventual CI). They are listed
|
||||
under "Building a service as a VM (for testing)"
|
||||
[here](https://nixos.wiki/wiki/Cheatsheet) (not linked since the page
|
||||
isn't set up very nicely).
|
||||
### New services
|
||||
|
||||
Whenever a new service is added, append an appropriate
|
||||
`,hostfwd=::3<port>:<port>` to the `QEMU_NET_OPTS` specified in
|
||||
`flake.nix` to bind the service to a host port.
|
||||
|
||||
There is no way to test this without binding to the host port, sadly.
|
||||
|
|
57
configuration/default.nix
Normal file
57
configuration/default.nix
Normal file
|
@ -0,0 +1,57 @@
|
|||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
imports = [ ];
|
||||
|
||||
nix = {
|
||||
package = pkgs.nixFlakes;
|
||||
extraOptions = ''
|
||||
experimental-features = nix-command flakes
|
||||
'';
|
||||
};
|
||||
|
||||
networking = {
|
||||
hostName = "tlaternet";
|
||||
|
||||
usePredictableInterfaceNames = false;
|
||||
useDHCP = false;
|
||||
interfaces.eth0.useDHCP = true;
|
||||
|
||||
firewall.allowedTCPPorts = [ 80 443 2222 2221 25565 ];
|
||||
};
|
||||
|
||||
time.timeZone = "Europe/London";
|
||||
|
||||
users.users.tlater = {
|
||||
isNormalUser = true;
|
||||
extraGroups = [ "wheel" ];
|
||||
openssh.authorizedKeys.keyFiles = [ ../keys/tlater.pub ];
|
||||
};
|
||||
|
||||
services.openssh = {
|
||||
enable = true;
|
||||
allowSFTP = false;
|
||||
passwordAuthentication = false;
|
||||
permitRootLogin = "no";
|
||||
ports = [ 2222 ];
|
||||
startWhenNeeded = true;
|
||||
};
|
||||
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
recommendedTlsSettings = true;
|
||||
recommendedOptimisation = true;
|
||||
recommendedGzipSettings = true;
|
||||
recommendedProxySettings = true;
|
||||
clientMaxBodySize = "10G";
|
||||
};
|
||||
|
||||
security.acme = {
|
||||
email = "tm@tlater.net";
|
||||
acceptTerms = true;
|
||||
};
|
||||
|
||||
virtualisation.oci-containers.backend = "podman";
|
||||
|
||||
system.stateVersion = "20.09";
|
||||
}
|
|
@ -2,9 +2,7 @@
|
|||
|
||||
{
|
||||
# Required for the lish console
|
||||
boot = {
|
||||
kernelParams = [ "console=ttyS0,19200n8" ];
|
||||
};
|
||||
boot.kernelParams = [ "console=ttyS0,19200n8" ];
|
||||
|
||||
boot.loader = {
|
||||
# Timeout to allow lish to connect
|
|
@ -1,68 +0,0 @@
|
|||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
./hardware-configuration.nix
|
||||
./linode.nix
|
||||
<nixpkgs/nixos/modules/profiles/headless.nix>
|
||||
|
||||
./modules/networked-docker-containers.nix
|
||||
|
||||
# FIXME: It'd be much nicer if these were imported further down,
|
||||
# and set inside the docker-containers set, instead of setting the
|
||||
# docker-containers set here.
|
||||
./services/nginx.nix
|
||||
./services/gitea.nix
|
||||
./services/nextcloud.nix
|
||||
./services/tlaternet.nix
|
||||
./services/minecraft.nix
|
||||
];
|
||||
|
||||
networking = {
|
||||
hostName = "tlaternet";
|
||||
|
||||
usePredictableInterfaceNames = false;
|
||||
# useDHCP is deprecated
|
||||
useDHCP = false;
|
||||
interfaces.eth0.useDHCP = true;
|
||||
|
||||
firewall = {
|
||||
enable = true;
|
||||
allowedTCPPorts = [
|
||||
80
|
||||
443
|
||||
2222
|
||||
2221
|
||||
25565
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
time.timeZone = "Europe/London";
|
||||
|
||||
users.users = {
|
||||
tlater = {
|
||||
isNormalUser = true;
|
||||
extraGroups = [ "wheel" "docker" ];
|
||||
openssh.authorizedKeys.keyFiles = [ ./keys/tlater.pub ];
|
||||
};
|
||||
};
|
||||
|
||||
services = {
|
||||
openssh = {
|
||||
enable = true;
|
||||
allowSFTP = false;
|
||||
passwordAuthentication = false;
|
||||
permitRootLogin = "no";
|
||||
ports = [ 2222 ];
|
||||
startWhenNeeded = true;
|
||||
};
|
||||
};
|
||||
|
||||
virtualisation.docker = {
|
||||
enable = true;
|
||||
autoPrune.enable = true;
|
||||
};
|
||||
|
||||
system.stateVersion = "19.09";
|
||||
}
|
BIN
etc/nixos/derivations/dist.tar.gz
(Stored with Git LFS)
BIN
etc/nixos/derivations/dist.tar.gz
(Stored with Git LFS)
Binary file not shown.
|
@ -1 +0,0 @@
|
|||
Subproject commit 114a87885e1b3852c4cf6fe9854c86045770b3e4
|
|
@ -1,15 +0,0 @@
|
|||
{ pkgs ? import <nixpkgs> {} }:
|
||||
|
||||
with pkgs;
|
||||
|
||||
# TODO: Once https://github.com/svanderburg/node2nix/issues/184 is
|
||||
# fixed, use a proper nixos package instead of a tarball.
|
||||
stdenv.mkDerivation {
|
||||
pname = "tlaternet-templates";
|
||||
version = "1.0";
|
||||
src = ./dist.tar.gz;
|
||||
installPhase = ''
|
||||
mkdir -p $out/srv/
|
||||
mv browser $out/srv/web
|
||||
'';
|
||||
}
|
|
@ -1,306 +0,0 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
let
|
||||
cfg = config.networked-docker-containers;
|
||||
|
||||
networkedDockerContainer =
|
||||
{ ... }: {
|
||||
|
||||
options = {
|
||||
|
||||
image = mkOption {
|
||||
type = with types; str;
|
||||
description = "Docker image to run.";
|
||||
example = "library/hello-world";
|
||||
};
|
||||
|
||||
imageFile = mkOption {
|
||||
type = with types; nullOr package;
|
||||
default = null;
|
||||
description = ''
|
||||
Path to an image file to load instead of pulling from a registry.
|
||||
If defined, do not pull from registry.
|
||||
|
||||
You still need to set the <literal>image</literal> attribute, as it
|
||||
will be used as the image name for docker to start a container.
|
||||
'';
|
||||
example = literalExample "pkgs.dockerTools.buildDockerImage {...};";
|
||||
};
|
||||
|
||||
cmd = mkOption {
|
||||
type = with types; listOf str;
|
||||
default = [];
|
||||
description = "Commandline arguments to pass to the image's entrypoint.";
|
||||
example = literalExample ''
|
||||
["--port=9000"]
|
||||
'';
|
||||
};
|
||||
|
||||
entrypoint = mkOption {
|
||||
type = with types; nullOr str;
|
||||
description = "Overwrite the default entrypoint of the image.";
|
||||
default = null;
|
||||
example = "/bin/my-app";
|
||||
};
|
||||
|
||||
environment = mkOption {
|
||||
type = with types; attrsOf str;
|
||||
default = {};
|
||||
description = "Environment variables to set for this container.";
|
||||
example = literalExample ''
|
||||
{
|
||||
DATABASE_HOST = "db.example.com";
|
||||
DATABASE_PORT = "3306";
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
log-driver = mkOption {
|
||||
type = types.str;
|
||||
default = "none";
|
||||
description = ''
|
||||
Logging driver for the container. The default of
|
||||
<literal>"none"</literal> means that the container's logs will be
|
||||
handled as part of the systemd unit. Setting this to
|
||||
<literal>"journald"</literal> will result in duplicate logging, but
|
||||
the container's logs will be visible to the <command>docker
|
||||
logs</command> command.
|
||||
|
||||
For more details and a full list of logging drivers, refer to the
|
||||
<link xlink:href="https://docs.docker.com/engine/reference/run/#logging-drivers---log-driver">
|
||||
Docker engine documentation</link>
|
||||
'';
|
||||
};
|
||||
|
||||
networks = mkOption {
|
||||
type = with types; listOf str;
|
||||
default = [];
|
||||
description = ''
|
||||
Docker networks to create and connect this container to.
|
||||
|
||||
The first network in this list will be connected with
|
||||
<literal>--network=</literal>, others after container
|
||||
creation with <command>docker network connect</command>.
|
||||
|
||||
Any networks will be created if they do not exist before
|
||||
the container is started.
|
||||
'';
|
||||
};
|
||||
|
||||
ports = mkOption {
|
||||
type = with types; listOf str;
|
||||
default = [];
|
||||
description = ''
|
||||
Network ports to publish from the container to the outer host.
|
||||
|
||||
Valid formats:
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
<literal><ip>:<hostPort>:<containerPort></literal>
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<literal><ip>::<containerPort></literal>
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<literal><hostPort>:<containerPort></literal>
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<literal><containerPort></literal>
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
Both <literal>hostPort</literal> and
|
||||
<literal>containerPort</literal> can be specified as a range of
|
||||
ports. When specifying ranges for both, the number of container
|
||||
ports in the range must match the number of host ports in the
|
||||
range. Example: <literal>1234-1236:1234-1236/tcp</literal>
|
||||
|
||||
When specifying a range for <literal>hostPort</literal> only, the
|
||||
<literal>containerPort</literal> must <emphasis>not</emphasis> be a
|
||||
range. In this case, the container port is published somewhere
|
||||
within the specified <literal>hostPort</literal> range. Example:
|
||||
<literal>1234-1236:1234/tcp</literal>
|
||||
|
||||
Refer to the
|
||||
<link xlink:href="https://docs.docker.com/engine/reference/run/#expose-incoming-ports">
|
||||
Docker engine documentation</link> for full details.
|
||||
'';
|
||||
example = literalExample ''
|
||||
[
|
||||
"8080:9000"
|
||||
]
|
||||
'';
|
||||
};
|
||||
|
||||
user = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = null;
|
||||
description = ''
|
||||
Override the username or UID (and optionally groupname or GID) used
|
||||
in the container.
|
||||
'';
|
||||
example = "nobody:nogroup";
|
||||
};
|
||||
|
||||
volumes = mkOption {
|
||||
type = with types; listOf str;
|
||||
default = [];
|
||||
description = ''
|
||||
List of volumes to attach to this container.
|
||||
|
||||
Note that this is a list of <literal>"src:dst"</literal> strings to
|
||||
allow for <literal>src</literal> to refer to
|
||||
<literal>/nix/store</literal> paths, which would difficult with an
|
||||
attribute set. There are also a variety of mount options available
|
||||
as a third field; please refer to the
|
||||
<link xlink:href="https://docs.docker.com/engine/reference/run/#volume-shared-filesystems">
|
||||
docker engine documentation</link> for details.
|
||||
'';
|
||||
example = literalExample ''
|
||||
[
|
||||
"volume_name:/path/inside/container"
|
||||
"/path/on/host:/path/inside/container"
|
||||
]
|
||||
'';
|
||||
};
|
||||
|
||||
workdir = mkOption {
|
||||
type = with types; nullOr str;
|
||||
default = null;
|
||||
description = "Override the default working directory for the container.";
|
||||
example = "/var/lib/hello_world";
|
||||
};
|
||||
|
||||
dependsOn = mkOption {
|
||||
type = with types; listOf str;
|
||||
default = [];
|
||||
description = ''
|
||||
Define which other containers this one depends on. They will be added to both After and Requires for the unit.
|
||||
|
||||
Use the same name as the attribute under <literal>services.docker-containers</literal>.
|
||||
'';
|
||||
example = literalExample ''
|
||||
services.docker-containers = {
|
||||
node1 = {};
|
||||
node2 = {
|
||||
dependsOn = [ "node1" ];
|
||||
}
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
extraDockerOptions = mkOption {
|
||||
type = with types; listOf str;
|
||||
default = [];
|
||||
description = "Extra options for <command>docker run</command>.";
|
||||
example = literalExample ''
|
||||
["--network=host"]
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
mkService = name: container: let
|
||||
mkAfter = map (x: "docker-${x}.service") container.dependsOn;
|
||||
in
|
||||
rec {
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "docker.service" "docker.socket" "docker-networks.service" ] ++ mkAfter;
|
||||
requires = after;
|
||||
|
||||
serviceConfig = {
|
||||
ExecStart = [ "${pkgs.docker}/bin/docker start -a ${name}" ];
|
||||
|
||||
ExecStartPre = [
|
||||
"-${pkgs.docker}/bin/docker rm -f ${name}"
|
||||
"-${pkgs.docker}/bin/docker image prune -f"
|
||||
] ++ (
|
||||
optional (container.imageFile != null)
|
||||
[ "${pkgs.docker}/bin/docker load -i ${container.imageFile}" ]
|
||||
) ++ [
|
||||
(
|
||||
concatStringsSep " \\\n " (
|
||||
[
|
||||
"${pkgs.docker}/bin/docker create"
|
||||
"--rm"
|
||||
"--name=${name}"
|
||||
"--log-driver=${container.log-driver}"
|
||||
] ++ optional (container.entrypoint != null)
|
||||
"--entrypoint=${escapeShellArg container.entrypoint}"
|
||||
++ (mapAttrsToList (k: v: "-e ${escapeShellArg k}=${escapeShellArg v}") container.environment)
|
||||
++ map (p: "-p ${escapeShellArg p}") container.ports
|
||||
++ optional (container.user != null) "-u ${escapeShellArg container.user}"
|
||||
++ map (v: "-v ${escapeShellArg v}") container.volumes
|
||||
++ optional (container.workdir != null) "-w ${escapeShellArg container.workdir}"
|
||||
++ optional (container.networks != []) "--network=${escapeShellArg (builtins.head container.networks)}"
|
||||
++ map escapeShellArg container.extraDockerOptions
|
||||
++ [ container.image ]
|
||||
++ map escapeShellArg container.cmd
|
||||
)
|
||||
)
|
||||
] ++ map (n: "${pkgs.docker}/bin/docker network connect ${escapeShellArg n} ${name}") (drop 1 container.networks);
|
||||
|
||||
ExecStop = ''${pkgs.bash}/bin/sh -c "[ $SERVICE_RESULT = success ] || ${pkgs.docker}/bin/docker stop ${name}"'';
|
||||
ExecStopPost = "-${pkgs.docker}/bin/docker rm -f ${name}";
|
||||
|
||||
### There is no generalized way of supporting `reload` for docker
|
||||
### containers. Some containers may respond well to SIGHUP sent to their
|
||||
### init process, but it is not guaranteed; some apps have other reload
|
||||
### mechanisms, some don't have a reload signal at all, and some docker
|
||||
### images just have broken signal handling. The best compromise in this
|
||||
### case is probably to leave ExecReload undefined, so `systemctl reload`
|
||||
### will at least result in an error instead of potentially undefined
|
||||
### behaviour.
|
||||
###
|
||||
### Advanced users can still override this part of the unit to implement
|
||||
### a custom reload handler, since the result of all this is a normal
|
||||
### systemd service from the perspective of the NixOS module system.
|
||||
###
|
||||
# ExecReload = ...;
|
||||
###
|
||||
|
||||
TimeoutStartSec = 0;
|
||||
TimeoutStopSec = 120;
|
||||
Restart = "no";
|
||||
};
|
||||
};
|
||||
|
||||
in
|
||||
{
|
||||
|
||||
options.networked-docker-containers = mkOption {
|
||||
default = {};
|
||||
type = types.attrsOf (types.submodule networkedDockerContainer);
|
||||
description = "Docker containers to run as systemd services.";
|
||||
};
|
||||
|
||||
config = mkIf (cfg != {}) {
|
||||
|
||||
systemd.services = mapAttrs' (n: v: nameValuePair "docker-${n}" (mkService n v)) cfg // {
|
||||
"docker-networks" = rec {
|
||||
after = [ "docker.service" "docker.socket" ];
|
||||
requires = after;
|
||||
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
ExecStart = map (
|
||||
n: ''${pkgs.bash}/bin/sh -c "${pkgs.docker}/bin/docker network inspect ${escapeShellArg n} > /dev/null || \
|
||||
${pkgs.docker}/bin/docker network create ${escapeShellArg n}"''
|
||||
) (unique (flatten (mapAttrsToList (_: c: c.networks) cfg)));
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
virtualisation.docker.enable = true;
|
||||
};
|
||||
}
|
BIN
etc/nixos/services/configs/minecraft.tar.gz
(Stored with Git LFS)
BIN
etc/nixos/services/configs/minecraft.tar.gz
(Stored with Git LFS)
Binary file not shown.
|
@ -1,173 +0,0 @@
|
|||
worker_processes auto;
|
||||
|
||||
error_log /var/log/nginx/error.log warn;
|
||||
pid /var/run/nginx.pid;
|
||||
|
||||
|
||||
events {
|
||||
worker_connections 1024;
|
||||
}
|
||||
|
||||
|
||||
http {
|
||||
include /etc/nginx/mime.types;
|
||||
default_type application/octet-stream;
|
||||
|
||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
||||
'$status $body_bytes_sent "$http_referer" '
|
||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
||||
|
||||
access_log /var/log/nginx/access.log main;
|
||||
|
||||
sendfile on;
|
||||
#tcp_nopush on;
|
||||
|
||||
keepalive_timeout 65;
|
||||
|
||||
set_real_ip_from 10.0.0.0/8;
|
||||
set_real_ip_from 172.16.0.0/12;
|
||||
set_real_ip_from 192.168.0.0/16;
|
||||
real_ip_header X-Real-IP;
|
||||
|
||||
#gzip on;
|
||||
|
||||
upstream php-handler {
|
||||
server nextcloud:9000;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
|
||||
# Add headers to serve security related headers
|
||||
# Before enabling Strict-Transport-Security headers please read into this
|
||||
# topic first.
|
||||
#add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always;
|
||||
#
|
||||
# WARNING: Only add the preload option once you read about
|
||||
# the consequences in https://hstspreload.org/. This option
|
||||
# will add the domain to a hardcoded list that is shipped
|
||||
# in all major browsers and getting removed from this list
|
||||
# could take several months.
|
||||
add_header Referrer-Policy "no-referrer" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header X-Download-Options "noopen" always;
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-Permitted-Cross-Domain-Policies "none" always;
|
||||
add_header X-Robots-Tag "none" always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
|
||||
# Remove X-Powered-By, which is an information leak
|
||||
fastcgi_hide_header X-Powered-By;
|
||||
|
||||
# Path to the root of your installation
|
||||
root /var/www/html;
|
||||
|
||||
location = /robots.txt {
|
||||
allow all;
|
||||
log_not_found off;
|
||||
access_log off;
|
||||
}
|
||||
|
||||
# The following 2 rules are only needed for the user_webfinger app.
|
||||
# Uncomment it if you're planning to use this app.
|
||||
#rewrite ^/.well-known/host-meta /public.php?service=host-meta last;
|
||||
#rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json last;
|
||||
|
||||
# The following rule is only needed for the Social app.
|
||||
# Uncomment it if you're planning to use this app.
|
||||
#rewrite ^/.well-known/webfinger /public.php?service=webfinger last;
|
||||
|
||||
location = /.well-known/carddav {
|
||||
return 301 $scheme://$host:$server_port/remote.php/dav;
|
||||
}
|
||||
|
||||
location = /.well-known/caldav {
|
||||
return 301 $scheme://$host:$server_port/remote.php/dav;
|
||||
}
|
||||
|
||||
# set max upload size
|
||||
client_max_body_size 10G;
|
||||
fastcgi_buffers 64 4K;
|
||||
|
||||
# Enable gzip but do not remove ETag headers
|
||||
gzip on;
|
||||
gzip_vary on;
|
||||
gzip_comp_level 4;
|
||||
gzip_min_length 256;
|
||||
gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
|
||||
gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
|
||||
|
||||
# Uncomment if your server is build with the ngx_pagespeed module
|
||||
# This module is currently not supported.
|
||||
#pagespeed off;
|
||||
|
||||
location / {
|
||||
rewrite ^ /index.php;
|
||||
}
|
||||
|
||||
location ~ ^\/(?:build|tests|config|lib|3rdparty|templates|data)\/ {
|
||||
deny all;
|
||||
}
|
||||
location ~ ^\/(?:\.|autotest|occ|issue|indie|db_|console) {
|
||||
deny all;
|
||||
}
|
||||
|
||||
location ~ ^\/(?:index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+)\.php(?:$|\/) {
|
||||
fastcgi_split_path_info ^(.+?\.php)(\/.*|)$;
|
||||
set $path_info $fastcgi_path_info;
|
||||
try_files $fastcgi_script_name =404;
|
||||
include fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_param PATH_INFO $path_info;
|
||||
# fastcgi_param HTTPS on;
|
||||
|
||||
# Avoid sending the security headers twice
|
||||
fastcgi_param modHeadersAvailable true;
|
||||
|
||||
# Enable pretty urls
|
||||
fastcgi_param front_controller_active true;
|
||||
fastcgi_pass php-handler;
|
||||
fastcgi_intercept_errors on;
|
||||
fastcgi_request_buffering off;
|
||||
}
|
||||
|
||||
location ~ ^\/(?:updater|oc[ms]-provider)(?:$|\/) {
|
||||
try_files $uri/ =404;
|
||||
index index.php;
|
||||
}
|
||||
|
||||
# Adding the cache control header for js, css and map files
|
||||
# Make sure it is BELOW the PHP block
|
||||
location ~ \.(?:css|js|woff2?|svg|gif|map)$ {
|
||||
try_files $uri /index.php$request_uri;
|
||||
add_header Cache-Control "public, max-age=15778463";
|
||||
# Add headers to serve security related headers (It is intended to
|
||||
# have those duplicated to the ones above)
|
||||
# Before enabling Strict-Transport-Security headers please read into
|
||||
# this topic first.
|
||||
#add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always;
|
||||
#
|
||||
# WARNING: Only add the preload option once you read about
|
||||
# the consequences in https://hstspreload.org/. This option
|
||||
# will add the domain to a hardcoded list that is shipped
|
||||
# in all major browsers and getting removed from this list
|
||||
# could take several months.
|
||||
add_header Referrer-Policy "no-referrer" always;
|
||||
add_header X-Content-Type-Options "nosniff" always;
|
||||
add_header X-Download-Options "noopen" always;
|
||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||
add_header X-Permitted-Cross-Domain-Policies "none" always;
|
||||
add_header X-Robots-Tag "none" always;
|
||||
add_header X-XSS-Protection "1; mode=block" always;
|
||||
|
||||
# Optional: Don't log access to assets
|
||||
access_log off;
|
||||
}
|
||||
|
||||
location ~ \.(?:png|html|ttf|ico|jpg|jpeg|bcmap|mp4|webm)$ {
|
||||
try_files $uri /index.php$request_uri;
|
||||
# Optional: Don't log access to other assets
|
||||
access_log off;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
client_max_body_size 16G;
|
|
@ -1,51 +0,0 @@
|
|||
{ ... }:
|
||||
|
||||
{
|
||||
networked-docker-containers = {
|
||||
gitea = {
|
||||
image = "gitea/gitea:latest";
|
||||
ports = [
|
||||
"2221:2221"
|
||||
];
|
||||
volumes = [
|
||||
"gitea:/data:Z"
|
||||
"/etc/timezone:/etc/timezone:ro"
|
||||
"/etc/localtime:/etc/localtime:ro"
|
||||
];
|
||||
environment = {
|
||||
VIRTUAL_PORT = "3000";
|
||||
VIRTUAL_HOST = "gitea.tlater.net";
|
||||
LETSENCRYPT_HOST = "gitea.tlater.net";
|
||||
|
||||
DB_TYPE = "postgres";
|
||||
DB_HOST = "gitea-postgres:5432";
|
||||
DB_NAME = "gitea";
|
||||
DB_USER = "gitea";
|
||||
DB_PASSWD = "/qNDDK9WCMuubfA7D8DFwfl9T+Gy2IMDvPhiNpcxZjY=";
|
||||
|
||||
RUN_MODE = "prod";
|
||||
DOMAIN = "gitea.tlater.net";
|
||||
SSH_PORT = "2221";
|
||||
};
|
||||
networks = [
|
||||
"webproxy"
|
||||
"gitea"
|
||||
];
|
||||
};
|
||||
|
||||
gitea-postgres = {
|
||||
image = "postgres:alpine";
|
||||
environment = {
|
||||
POSTGRES_DB = "gitea";
|
||||
POSTGRES_USER = "gitea";
|
||||
POSTGRES_PASSWORD = "/qNDDK9WCMuubfA7D8DFwfl9T+Gy2IMDvPhiNpcxZjY=";
|
||||
};
|
||||
volumes = [
|
||||
"gitea-db-data-new:/var/lib/postgresql/data"
|
||||
];
|
||||
networks = [
|
||||
"gitea"
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,130 +0,0 @@
|
|||
{ pkgs, ... }:
|
||||
|
||||
let
|
||||
entrypoint = pkgs.writeScript "entrypoint.sh" ''
|
||||
#!${pkgs.bash}/bin/bash
|
||||
${pkgs.busybox}/bin/mkdir -p /var/lib/
|
||||
${pkgs.gzip}/bin/gzip -dc ${./configs/minecraft.tar.gz} | ${pkgs.gnutar}/bin/tar -xf - -C /var/lib
|
||||
echo 'eula=true' > /var/lib/minecraft/eula.txt
|
||||
${pkgs.busybox}/bin/cp -f ${properties} /var/lib/minecraft/server.properties
|
||||
$@
|
||||
'';
|
||||
ops = pkgs.writeText "ops.json" (builtins.toJSON [
|
||||
{
|
||||
uuid = "140d177a-966f-41b8-a4c0-e305babd291b";
|
||||
name = "TLATER";
|
||||
level = 4;
|
||||
bypassesPlayerLimit = true;
|
||||
}
|
||||
]);
|
||||
whitelist = pkgs.writeText "whitelist.json" (builtins.toJSON [
|
||||
{
|
||||
uuid = "59cd1648-14a4-4bcf-8f5a-2e1bde678f2c";
|
||||
name = "romino25";
|
||||
}
|
||||
{
|
||||
uuid = "0ab6e3d1-544a-47e7-8538-2e6c248e49a4";
|
||||
name = "lasi25";
|
||||
}
|
||||
{
|
||||
uuid = "140d177a-966f-41b8-a4c0-e305babd291b";
|
||||
name = "TLATER";
|
||||
}
|
||||
]);
|
||||
properties = pkgs.writeText "server.properties" ''
|
||||
#Minecraft server properties
|
||||
#Sun Jul 19 16:04:54 GMT 2020
|
||||
max-tick-time=60000
|
||||
generator-settings=
|
||||
allow-nether=true
|
||||
force-gamemode=false
|
||||
gamemode=0
|
||||
enable-query=false
|
||||
player-idle-timeout=0
|
||||
difficulty=1
|
||||
spawn-monsters=true
|
||||
op-permission-level=4
|
||||
pvp=false
|
||||
snooper-enabled=true
|
||||
level-type=DEFAULT
|
||||
hardcore=false
|
||||
enable-command-block=false
|
||||
max-players=4
|
||||
network-compression-threshold=256
|
||||
resource-pack-sha1=
|
||||
max-world-size=29999984
|
||||
server-port=25565
|
||||
server-ip=
|
||||
spawn-npcs=true
|
||||
allow-flight=true
|
||||
level-name=world
|
||||
view-distance=15
|
||||
resource-pack=
|
||||
spawn-animals=true
|
||||
white-list=true
|
||||
generate-structures=true
|
||||
online-mode=true
|
||||
max-build-height=256
|
||||
level-seed=
|
||||
prevent-proxy-connections=false
|
||||
use-native-transport=true
|
||||
motd=Adventures met die broers
|
||||
enable-rcon=false
|
||||
'';
|
||||
|
||||
in
|
||||
{
|
||||
docker-containers = {
|
||||
minecraft = {
|
||||
image = "tlaternet/minecraft";
|
||||
imageFile = pkgs.dockerTools.buildImage {
|
||||
name = "tlaternet/minecraft";
|
||||
tag = "latest";
|
||||
config = {
|
||||
Entrypoint = [ "${entrypoint}" ];
|
||||
Cmd = [ "${pkgs.jre}/bin/java"
|
||||
"-Xms2G"
|
||||
"-Xmx2G"
|
||||
# Using recommended flags from https://mcflags.emc.gs
|
||||
"-XX:+UseG1GC"
|
||||
"-XX:+ParallelRefProcEnabled"
|
||||
"-XX:MaxGCPauseMillis=200"
|
||||
"-XX:+UnlockExperimentalVMOptions"
|
||||
"-XX:+DisableExplicitGC"
|
||||
"-XX:+AlwaysPreTouch"
|
||||
"-XX:G1NewSizePercent=30"
|
||||
"-XX:G1MaxNewSizePercent=40"
|
||||
"-XX:G1HeapRegionSize=8M"
|
||||
"-XX:G1ReservePercent=20"
|
||||
"-XX:G1HeapWastePercent=5"
|
||||
"-XX:G1MixedGCCountTarget=4"
|
||||
"-XX:InitiatingHeapOccupancyPercent=15"
|
||||
"-XX:G1MixedGCLiveThresholdPercent=90"
|
||||
"-XX:G1RSetUpdatingPauseTimePercent=5"
|
||||
"-XX:SurvivorRatio=32"
|
||||
"-XX:+PerfDisableSharedMem"
|
||||
"-XX:MaxTenuringThreshold=1"
|
||||
"-jar"
|
||||
"/var/lib/minecraft/forge-1.12.2-14.23.5.2854.jar"
|
||||
"nogui"
|
||||
];
|
||||
Volumes = {
|
||||
"/var/lib/minecraft/world" = {};
|
||||
};
|
||||
WorkingDir = "/var/lib/minecraft";
|
||||
ExposedPorts = {
|
||||
"25565" = {};
|
||||
};
|
||||
};
|
||||
};
|
||||
ports = [
|
||||
"25565:25565"
|
||||
];
|
||||
volumes = [
|
||||
"minecraft:/var/lib/minecraft/world"
|
||||
"${ops}:/var/lib/minecraft/ops.json:ro"
|
||||
"${whitelist}:/var/lib/minecraft/whitelist.json:ro"
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
{ ... }:
|
||||
|
||||
{
|
||||
networked-docker-containers = {
|
||||
nextcloud = {
|
||||
image = "nextcloud:fpm-alpine";
|
||||
dependsOn = ["nextcloud-postgres"];
|
||||
volumes = [
|
||||
"nextcloud-apps:/var/www/html/custom_apps"
|
||||
"nextcloud-config:/var/www/html/config"
|
||||
"nextcloud-data:/var/www/html/data"
|
||||
];
|
||||
environment = {
|
||||
POSTGRES_DB = "nextcloud";
|
||||
POSTGRES_USER = "nextcloud";
|
||||
POSTGRES_HOST = "nextcloud-postgres";
|
||||
POSTGRES_PASSWORD = "rI7t7Nek1yGA9ucrRc7Uhy0jcjwPjnXa8me4o8tJON8=";
|
||||
OVERWRITEPROTOCOL = "https";
|
||||
};
|
||||
networks = [
|
||||
"nextcloud"
|
||||
];
|
||||
extraDockerOptions = [
|
||||
"--domainname=nextcloud.tlater.net"
|
||||
];
|
||||
};
|
||||
|
||||
nextcloud-cron = {
|
||||
image = "nextcloud:fpm-alpine";
|
||||
entrypoint = "/cron.sh";
|
||||
dependsOn = ["nextcloud-postgres"];
|
||||
extraDockerOptions = [
|
||||
"--volumes-from"
|
||||
"nextcloud"
|
||||
];
|
||||
networks = [
|
||||
"nextcloud"
|
||||
];
|
||||
};
|
||||
|
||||
nextcloud-nginx = {
|
||||
image = "nginx:alpine";
|
||||
dependsOn = ["nextcloud"];
|
||||
environment = {
|
||||
LETSENCRYPT_HOST = "nextcloud.tlater.net";
|
||||
VIRTUAL_HOST = "nextcloud.tlater.net";
|
||||
};
|
||||
volumes = [
|
||||
"${./configs/nginx-nextcloud.conf}:/etc/nginx/nginx.conf:ro"
|
||||
];
|
||||
networks = [
|
||||
"webproxy"
|
||||
"nextcloud"
|
||||
];
|
||||
extraDockerOptions = [
|
||||
"--volumes-from"
|
||||
"nextcloud"
|
||||
];
|
||||
};
|
||||
|
||||
nextcloud-postgres = {
|
||||
image = "postgres:alpine";
|
||||
environment = {
|
||||
POSTGRES_DB = "nextcloud";
|
||||
POSTGRES_USER = "nextcloud";
|
||||
POSTGRES_PASSWORD = "rI7t7Nek1yGA9ucrRc7Uhy0jcjwPjnXa8me4o8tJON8=";
|
||||
};
|
||||
volumes = [
|
||||
"nextcloud-db-data-new:/var/lib/postgresql/data"
|
||||
];
|
||||
networks = [
|
||||
"nextcloud"
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
{ ... }:
|
||||
|
||||
{
|
||||
networked-docker-containers = {
|
||||
nginx-proxy = {
|
||||
image = "jwilder/nginx-proxy:alpine";
|
||||
ports = [
|
||||
"80:80"
|
||||
"443:443"
|
||||
];
|
||||
volumes = [
|
||||
"${./configs/nginx-proxy.conf}:/etc/nginx/conf.d/general.conf:ro"
|
||||
# So that we can watch new containers come up
|
||||
"/var/run/docker.sock:/tmp/docker.sock:ro"
|
||||
# So that we can access generated certs
|
||||
"nginx-certs:/etc/nginx/certs:ro"
|
||||
# So that we can write challenge files for letsencrypt auth
|
||||
"nginx-challenges:/usr/share/nginx/html"
|
||||
# So that we can modify config on-the-fly to set up challenge
|
||||
# files
|
||||
"nginx-conf:/etc/nginx/vhost.d"
|
||||
];
|
||||
environment = {
|
||||
DHPARAM_GENERATION = "false"; # Provided by nginx-proxy-letsencrypt
|
||||
};
|
||||
networks = [
|
||||
"webproxy"
|
||||
];
|
||||
};
|
||||
|
||||
nginx-proxy-letsencrypt = {
|
||||
image = "jrcs/letsencrypt-nginx-proxy-companion";
|
||||
dependsOn = ["nginx-proxy"];
|
||||
volumes = [
|
||||
"/var/run/docker.sock:/var/run/docker.sock:ro"
|
||||
"nginx-certs:/etc/nginx/certs"
|
||||
];
|
||||
environment = {
|
||||
DEFAULT_EMAIL = "tm@tlater.net";
|
||||
};
|
||||
extraDockerOptions = [
|
||||
"--volumes-from"
|
||||
"nginx-proxy"
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
{ pkgs, ... }:
|
||||
|
||||
let
|
||||
tlaternet = import ../derivations/tlaternet { inherit pkgs; };
|
||||
tlaternet-templates = import ../derivations/tlaternet-templates.nix { inherit pkgs; };
|
||||
|
||||
in
|
||||
{
|
||||
networked-docker-containers = {
|
||||
web = {
|
||||
image = "tlaternet/web";
|
||||
imageFile = pkgs.dockerTools.buildImage {
|
||||
name = "tlaternet/web";
|
||||
tag = "latest";
|
||||
contents = tlaternet;
|
||||
config = {
|
||||
Cmd = [ "${tlaternet}/bin/tlaternet" ];
|
||||
Volumes = {
|
||||
"/srv/mail" = {};
|
||||
};
|
||||
Env = [
|
||||
"ROCKET_PORT=80"
|
||||
"ROCKET_TEMPLATE_DIR=${tlaternet-templates}/srv/web"
|
||||
];
|
||||
ExposedPorts = {
|
||||
"80" = {};
|
||||
};
|
||||
};
|
||||
};
|
||||
volumes = [
|
||||
"tlaternet-mail:/srv/mail"
|
||||
];
|
||||
environment = {
|
||||
VIRTUAL_HOST = "tlater.net,www.tlater.net";
|
||||
LETSENCRYPT_HOST = "tlater.net,www.tlater.net";
|
||||
};
|
||||
networks = [
|
||||
"webproxy"
|
||||
];
|
||||
extraDockerOptions = [
|
||||
"--domainname=tlater.net"
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
60
flake.lock
Normal file
60
flake.lock
Normal file
|
@ -0,0 +1,60 @@
|
|||
{
|
||||
"nodes": {
|
||||
"flake-utils": {
|
||||
"locked": {
|
||||
"lastModified": 1617631617,
|
||||
"narHash": "sha256-PARRCz55qN3gy07VJZIlFeOX420d0nGF0RzGI/9hVlw=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "b2c27d1a81b0dc266270fa8aeecebbd1807fc610",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixos-hardware": {
|
||||
"locked": {
|
||||
"lastModified": 1617690895,
|
||||
"narHash": "sha256-5TUizPI+ibn/LBzevTIIyIZ1XeLl3HU0PTRk7H6AKTQ=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixos-hardware",
|
||||
"rev": "7c00c8b5cab5dedb6519eabba7ca6d069e2dfdae",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "master",
|
||||
"repo": "nixos-hardware",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1618149891,
|
||||
"narHash": "sha256-Sz3DzI1k49Puq+F5KRBsaN3gRXHDzCTG6AwK29Znw0M=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "a7ff7a57c96588fd89370568b72751dd15d24e72",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixos-20.09",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"nixos-hardware": "nixos-hardware",
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
47
flake.nix
Normal file
47
flake.nix
Normal file
|
@ -0,0 +1,47 @@
|
|||
{
|
||||
description = "tlater.net host configuration";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:nixos/nixpkgs/nixos-20.09";
|
||||
nixos-hardware.url = "github:nixos/nixos-hardware/master";
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
};
|
||||
|
||||
outputs = { nixpkgs, nixos-hardware, flake-utils, ... }@inputs:
|
||||
{
|
||||
nixosConfigurations = {
|
||||
tlaternet = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
|
||||
modules = [
|
||||
(import ./configuration)
|
||||
(import ./configuration/linode.nix)
|
||||
(import ./configuration/hardware-configuration.nix)
|
||||
nixpkgs.modules.headless
|
||||
];
|
||||
};
|
||||
|
||||
vm = nixpkgs.lib.nixosSystem {
|
||||
system = "x86_64-linux";
|
||||
|
||||
modules = [
|
||||
(import ./configuration)
|
||||
({ ... }: {
|
||||
users.users.tlater.password = "insecure";
|
||||
# virtualisation.memorySize = 3941;
|
||||
# virtualisation.cores = 2;
|
||||
})
|
||||
];
|
||||
};
|
||||
};
|
||||
} // flake-utils.lib.eachDefaultSystem (system: {
|
||||
devShell = with nixpkgs.legacyPackages.${system};
|
||||
mkShell {
|
||||
buildInputs = [ nixfmt git-lfs ];
|
||||
shellHook = ''
|
||||
export QEMU_OPTS="-m 3941 -smp 2"
|
||||
export QEMU_NET_OPTS="hostfwd=::3022-:2222,hostfwd=::3080-:80,hostfwd=::3443-:443,hostfwd=::3021-:2221,hostfwd=::25565-:25565"
|
||||
'';
|
||||
};
|
||||
});
|
||||
}
|
Loading…
Reference in a new issue