cloudTool = ./websites/tools/cloud;
davTool = ./websites/tools/dav;
+ vpnTool = ./websites/tools/vpn;
dbTool = ./websites/tools/db;
diasporaTool = ./websites/tools/diaspora;
etherTool = ./websites/tools/ether;
ssh = ./ssh;
monitoring = ./monitoring;
status = ./monitoring/status.nix;
+ vpn = ./vpn;
environment = ./environment.nix;
system = ./system.nix;
};
};
};
+ vpn = mkOption {
+ description = "VPN configuration";
+ type = attrsOf (submodule {
+ options = {
+ prefix = mkOption { type = str; description = "ipv6 prefix for the vpn subnet"; };
+ privateKey = mkOption { type = str; description = "Private key for the host"; };
+ publicKey = mkOption { type = str; description = "Public key for the host"; };
+ };
+ });
+ };
mail = mkOption {
description = "Mail configuration";
type = submodule {
myServices.websites.enable = true;
myServices.mail.enable = true;
myServices.ejabberd.enable = true;
+ myServices.vpn.enable = true;
services.pure-ftpd.enable = true;
services.duplyBackup.enable = true;
services.duplyBackup.profiles.oldies.rootDir = "/var/lib/oldies";
--- /dev/null
+{ config, pkgs, lib, ... }:
+let
+ cfg = config.myServices.vpn;
+in
+{
+ options.myServices = {
+ vpn.enable = lib.mkEnableOption "Enable vpn service";
+ };
+
+ config = lib.mkIf cfg.enable {
+ secrets.keys = [
+ {
+ dest = "tinc/key.priv";
+ user = "root";
+ group = "root";
+ permissions = "0400";
+ text = config.myEnv.vpn.eldiron.privateKey;
+ }
+ {
+ dest = "tinc/key.pub";
+ user = "root";
+ group = "root";
+ permissions = "0400";
+ text = config.myEnv.vpn.eldiron.publicKey;
+ }
+ ];
+ networking.firewall.allowedTCPPorts = [ 655 1194 ];
+ system.activationScripts.tinc = let
+ configFiles = pkgs.runCommand "tinc-files" {
+ mainInterface = "eth0";
+ hostName = "ImmaeEu";
+ network = "Immae";
+ keyFile = config.secrets.fullPaths."tinc/key.priv";
+ } ''
+ mkdir -p $out
+ for i in ${./tinc}/*; do
+ substituteAll $i $out/$(basename $i)
+ done
+ '';
+ in ''
+ install -m750 -o root -g root -d /var/lib/tinc/ /var/lib/tinc/Immae
+ install -m700 -o root -g root -t /var/lib/tinc/Immae ${configFiles}/{host-*,tinc-*}
+ install -m400 -o root -g root -t /var/lib/tinc/Immae ${configFiles}/tinc.conf
+ if [ ! -d /var/lib/tinc/Immae/hosts ]; then
+ ${pkgs.git}/bin/git clone -b master https://git.immae.eu/perso/Immae/Config/tinc/hosts /var/lib/tinc/Immae/hosts
+ fi
+ '';
+
+ systemd.services.tinc-Immae = {
+ description = "Tinc Daemon - Immae";
+ wantedBy = [ "multi-user.target" ];
+ after = [ "network.target" ];
+ path = [ pkgs.tinc pkgs.bashInteractive pkgs.iproute pkgs.gnused pkgs.gawk pkgs.git pkgs.glibc ];
+ serviceConfig = {
+ Type = "simple";
+ Restart = "always";
+ RestartSec = "3";
+ ExecStart = "${pkgs.tinc}/bin/tincd -d1 -D -c /var/lib/tinc/Immae --pidfile /run/tinc.Immae.pid";
+ };
+ };
+ };
+}
--- /dev/null
+#!/usr/bin/env bash
+
+SUBDOMAIN=$(echo "$NODE" | sed -e "s/\([A-Z][a-z0-9]*\)/\L\1 /g;" | awk '{ for (i=NF; i>1; i--) printf("%s.",$i); print $1; }')
+NODEIPS=`getent hosts ${SUBDOMAIN}.immae.eu | cut -d' ' -f1 | tr "\\n" ' '`
+for NODEIP in $NODEIPS; do
+ ip neigh del proxy $NODEIP dev @mainInterface@
+done
--- /dev/null
+#!/usr/bin/env bash
+
+SUBDOMAIN=$(echo "$NODE" | sed -e "s/\([A-Z][a-z0-9]*\)/\L\1 /g;" | awk '{ for (i=NF; i>1; i--) printf("%s.",$i); print $1; }')
+while [ -z "$NODEIPS" ]; do
+ NODEIPS=`getent hosts ${SUBDOMAIN}.immae.eu | cut -d' ' -f1 | tr "\\n" ' '`
+ sleep 5
+done
+for NODEIP in $NODEIPS; do
+ ip neigh add proxy $NODEIP dev @mainInterface@
+done
+(cd /var/lib/tinc/@network@/hosts && git pull -q origin master) || true
--- /dev/null
+#!/bin/sh
+# This file closes down the tap device.
+
+echo 0 > /proc/sys/net/ipv6/conf/@mainInterface@/proxy_ndp
+echo 0 > /proc/sys/net/ipv6/conf/all/forwarding
+
+GWIP=`getent hosts gw.vpn.immae.eu | head -n1 | cut -d' ' -f1`
+
+ip neigh del proxy $GWIP dev eth0
+
+ip -6 addr del $GWIP/96 dev $INTERFACE
+ip -6 link set $INTERFACE down
--- /dev/null
+#!/usr/bin/env bash
+
+echo 1 > /proc/sys/net/ipv6/conf/@mainInterface@/proxy_ndp
+echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
+
+SUBNET=`getent hosts sn.vpn.immae.eu | head -n1 | cut -d' ' -f1`
+GWIP=`getent hosts gw.vpn.immae.eu | head -n1 | cut -d' ' -f1`
+
+ip -6 link set $INTERFACE up mtu 1280 txqueuelen 1000
+
+ip -6 addr add $GWIP/96 dev $INTERFACE
+ip -6 route add $SUBNET/80 dev $INTERFACE
+
+ip neigh add proxy $GWIP dev @mainInterface@
--- /dev/null
+BindToAddress = * 655
+BindToAddress = * 1194
+
+Name = @hostName@
+Interface = vpn6
+
+Mode = switch
+
+Device = /dev/net/tun
+GraphDumpFile = /var/lib/tinc/@network@/tinc_graph
+PrivateKeyFile = @keyFile@
root = "/var/lib/ftp/tools.immae.eu";
extraConfig = [
''
+ RedirectMatch 301 ^/vpn(.*)$ https://vpn.immae.eu$1
RedirectMatch 301 ^/roundcube(.*)$ https://mail.immae.eu/roundcube$1
RedirectMatch 301 ^/jappix(.*)$ https://im.immae.fr/converse
RedirectMatch 301 ^/jappix(.*)$ https://im.immae.fr/converse
+ RedirectMatch 301 ^/vpn(.*)$ https://vpn.immae.eu$1
+
RedirectMatch 301 ^/(.*)$ https://tools.immae.eu/$1
''
];
--- /dev/null
+{ lib, pkgs, config, ... }:
+let
+ cfg = config.myServices.vpn;
+in {
+ config = lib.mkIf cfg.enable {
+ services.websites.env.tools.vhostConfs.vpn = {
+ certName = "eldiron";
+ addToCerts = true;
+ hosts = [ "vpn.immae.eu" ];
+ root = "/run/current-system/webapps/_vpn";
+ };
+
+ myServices.websites.webappDirs._vpn = ./www;
+ };
+}
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>VPN configuration</title>
+ <meta content='text/html; charset=UTF-8' http-equiv='Content-Type'>
+ <link rel="stylesheet" href="style.css" type="text/css" />
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
+ </head>
+ <body>
+ <div class="instructions">
+ <h2>Installation</h2>
+ <ul>
+ <li>Installer tinc</li>
+ <li>Créer un fichier /etc/tinc/Immae/tinc.conf sur ce modèle, en remplaçant la ligne <code>A choisir</code> par un nom de la forme DomaineMachine. La machine sera accessible par <code>machine.domaine.immae.eu</code> par la suite
+ <pre>
+Name = A choisir
+Mode = switch
+Interface = vpn6
+ConnectTo = ImmaeEu
+
+# The tap device tinc will use.
+# Default is /dev/tap0 for ethertap or FreeBSD,
+# /dev/tun0 for Solaris and OpenBSD,
+# and /dev/net/tun for Linux tun/tap device.
+Device = /dev/net/tun
+LocalDiscovery = yes
+ </pre>
+ </li>
+ <li>Vérifier l'existence du device indiqué à la ligne "<code>Device</code>" dans le système.
+ <pre>ls /dev/net/tun</pre>
+ </li>
+ <li><em class="important">Si tinc tourne déjà, l'arrêter !!</em></li>
+ <li>Générer les clés :
+ <pre>tincd -K -n Immae</pre>
+ Stocker la clé privée dans <code>/etc/tinc/Immae/rsa_key.priv</code> et la clé publique dans un autre dossier<br />
+ (<em>pas <code>/etc/tinc/Immae/hosts/</code> comme proposé par défaut</em>).<br />
+ L'endroit importe peu, elle ne sera pas conservée.</li>
+ <li>M'envoyer le nom choisi dans <code>tinc.conf</code>, et la clé publique</li>
+ <li>Cloner le dépôt des hôtes du réseau
+ <pre>
+cd /etc/tinc/Immae
+git clone https://git.immae.eu/perso/Immae/Config/tinc/hosts
+ </pre>
+ </li>
+ <li>Une fois que j'ai confirmé avoir reçu la clé :
+ <pre>
+cd /etc/tinc/Immae/hosts
+git pull origin master
+ </pre>
+ </li>
+ <li>Uniquement pour Debian/Ubuntu: Ajouter <code>Immae</code> dans <code>/etc/tinc/nets.boot</code> (créer le fichier si nécessaire).</li>
+ <li>Selon le système, démarrer tinc :
+ <pre>
+/etc/init.d/tinc start
+ </pre>
+ ou
+ <pre>
+systemctl enable tincd@Immae.service
+systemctl start tincd@Immae.service
+ </pre>
+ </li>
+ </ul>
+
+ <h2>Choix d'ip</h2>
+ <ul>
+ <li>Choisir une ip : <code>2001:aaaa:b:cccc:d::xxxx:yyyy/96</code> (le préfixe <code>2001:aaaa:b:cccc:d</code> est imposé). Choix uniquement sur le <code>yyyy</code> (n'importe quel nombre entre <code>1</code> et <code>ffff</code>), le <code>xxxx</code> est dépendant du domaine</li>
+ <li>M'envoyer le choix de l'ip</li>
+
+ <li>Si on veut éviter de passer systématiquement par le serveur immae.eu (Par
+ défaut linux préfère l'ipv6 dès qu'il en a possibilité), modifier le fichier
+ <code>/etc/gai.conf</code>. Quelques lignes à décommenter, tout est déjà dans le fichier :
+ <pre>
+(...)
+#
+precedence ::1/128 50
+precedence ::/0 40
+precedence 2002::/16 30
+precedence ::/96 20
+#precedence ::ffff:0:0/96 10
+#
+# For sites which prefer IPv4 connections change the last line to
+#
+precedence ::ffff:0:0/96 100
+(...)
+ </pre>
+ </li>
+ </ul>
+ </div>
+ </body>
+</html>
--- /dev/null
+* {
+ margin:0;
+ padding:0;
+ -webkit-box-sizing:border-box;
+ -moz-box-sizing:border-box;
+ box-sizing: border-box;
+}
+
+html {
+ min-height:100%;
+ border-top:10px solid #ECEEF1;
+ border-bottom:10px solid #ECEEF1;
+ color:#61666c;
+ font-weight:400;
+ font-size:1em;
+ font-family:'Open Sans', sans-serif;
+ line-height:2em;
+}
+body {
+ padding:20px;
+ -webkit-backface-visibility:hidden;
+}
+code {
+ font-family:consolas,monospace;
+}
+a {
+ color:#61666c;
+ text-decoration:none;
+}
+a, img {
+ border:none;
+ outline:none
+}
+a:hover {
+ color:#2a2a2a;
+}
+
+.instructions {
+ margin:0 auto;
+ padding-top:20px;
+ max-width:80%;
+}
+
+.instructions a {
+ text-decoration: underline;
+}
+
+.instructions h2 {
+ margin-top: 10px;
+}
+.instructions em.important:before {
+ content: "⚠ Important ⚠ ";
+ color: red;
+}
+.instructions pre {
+ width: 50em;
+ padding: 10px 15px;
+ display: table;
+ border: 1px inset black;
+ line-height: 1em;
+}