├── .gitignore ├── LICENSE ├── README.md ├── server ├── base.nix ├── configuration.nix ├── container │ └── nextcloud.nix ├── pkg │ ├── jank-benchmark.nix │ ├── safepaste.nix │ └── wordy-word.nix ├── program │ ├── admin.nix │ └── essential.nix ├── service │ ├── acme.nix │ ├── data │ │ ├── park-index.html │ │ └── upgrade-rainloop │ ├── domain-parking.nix │ ├── dovecot.nix │ ├── fail2ban.nix │ ├── gpg.nix │ ├── httpd.nix │ ├── jank-benchmark.nix │ ├── jank-license.nix │ ├── opendkim.nix │ ├── postfix.nix │ ├── radicale.nix │ ├── rainloop.nix │ ├── safepaste.nix │ ├── spamassassin.nix │ ├── taskserver.nix │ ├── upload.jeaye.com-tmp.nix │ └── wordy-word.nix ├── system │ ├── environment.nix │ ├── network.nix │ ├── security.nix │ └── user.nix ├── user │ ├── fu-er.nix │ ├── git.nix │ ├── irc.nix │ ├── jeaye.nix │ └── okletsplay.nix └── util │ ├── acme.nix │ └── http.nix ├── shared ├── configuration.nix ├── service │ ├── locate.nix │ ├── ssh.nix │ └── time.nix └── system │ ├── boot.nix │ ├── environment.nix │ ├── network.nix │ ├── security.nix │ ├── systemd.nix │ └── user.nix └── workstation ├── configuration.nix ├── hardware-configuration.nix ├── program └── essential.nix ├── service ├── docker.nix ├── ssh.nix ├── virtualbox.nix └── x11.nix ├── system ├── boot.nix ├── environment.nix ├── network.nix ├── network │ └── malicious-host.nix ├── security.nix ├── sound.nix ├── usb.nix └── user.nix └── user ├── jeaye.nix └── jeaye ├── data └── dotfiles │ ├── Xresources │ ├── bash_profile │ ├── bashrc │ ├── bashrc-alias │ ├── bashrc-less │ ├── bashrc-prompt │ ├── bin │ ├── define │ ├── i3data │ ├── lock │ ├── super-nice │ ├── upload │ └── youtube-dl-audio │ ├── config │ └── i3 │ │ └── config │ ├── gitconfig │ ├── gitignore │ ├── i3status.conf │ ├── lein │ └── profiles.clj │ ├── mpv │ └── mpv.conf │ ├── tmux.conf │ └── xinitrc ├── desktop.nix ├── gaming.nix ├── home.nix ├── pkg └── vimrc.nix └── program.nix /.gitignore: -------------------------------------------------------------------------------- 1 | /hardware-configuration.nix 2 | /configuration.nix 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright © 2017 Jesse 'Jeaye' Wilkerson. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted, free of charge, provided that the following 5 | conditions are met: 6 | 7 | Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | Redistributions in any form must be accompanied by information on how to obtain 15 | complete source code for the distributed software and any accompanying software 16 | that uses the distributed software. The source code must either be included in 17 | the distribution or be available free of charge. For an executable file, 18 | complete source code means the source code for all modules it contains. It does 19 | not include source code for modules or files that typically accompany the major 20 | components of the operating system on which the executable file runs. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 25 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | SOFTWARE. 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | nix-files 2 | === 3 | 4 | These configurations declaratively describe both my VPS, running multiple 5 | websites and services, as well we my workstation. These machines run using the 6 | [NixOS Linux distribution](http://nixos.org). 7 | 8 | The main entry point describing the core system is `configuration.nix`; from 9 | there, each item is split categorically. Each installation will provide a link 10 | from `/etc/nixos/configuration.nix` to either `workstation/configuration.nix` or 11 | `server/configuration.nix`. 12 | 13 | ## Workstation 14 | ### Managed bits 15 | ### Non-managed bits 16 | 17 | ## Server 18 | ### Managed bits 19 | * System 20 | * GRUB, time, network, firewall, users, packages, etc 21 | * Nearly three dozen websites 22 | * Mail server 23 | * IMAP (dovecot) + SMTP (postfix) + DKIM 24 | * Rainloop web client 25 | * [safepaste](https://github.com/jeaye/safepaste) service 26 | * [jank benchmark visualizer](http://bench.jank-lang.org/) service 27 | * caldav service 28 | * SSL Certs (Let's Encrypt) 29 | 30 | ### Non-managed bits 31 | * User passwords 32 | -------------------------------------------------------------------------------- /server/base.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | imports = 5 | [ 6 | ../shared/configuration.nix 7 | 8 | ## System 9 | ./system/environment.nix 10 | ./system/network.nix 11 | ./system/security.nix 12 | 13 | ## Global programs 14 | ./program/essential.nix 15 | 16 | ## Users 17 | ./system/user.nix 18 | ]; 19 | } 20 | -------------------------------------------------------------------------------- /server/configuration.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | # TODO: Add automatic blacklist lookup 4 | # http://www.blacklistalert.org/ 5 | # https://mxtoolbox.com/SuperTool.aspx?action=blacklist%3a192.241.218.198&run=toolpage 6 | # http://mail-blacklist-checker.online-domain-tools.com/ 7 | 8 | { 9 | imports = 10 | [ 11 | ../hardware-configuration.nix # Auto-generated by nixos 12 | ../nixos-in-place.nix # Auto-generated by nixos-in-place 13 | 14 | ## Base system 15 | ./base.nix 16 | 17 | ## Global programs 18 | ./program/admin.nix 19 | 20 | ## Users 21 | ./system/user.nix 22 | 23 | ./user/irc.nix 24 | ./user/git.nix 25 | ./user/jeaye.nix 26 | ./user/fu-er.nix 27 | ./user/okletsplay.nix 28 | 29 | ## Services 30 | ./service/acme.nix 31 | ./service/httpd.nix 32 | ./service/domain-parking.nix 33 | ./service/postfix.nix 34 | ./service/dovecot.nix 35 | ./service/opendkim.nix 36 | ./service/spamassassin.nix 37 | #./service/safepaste.nix 38 | #./service/jank-benchmark.nix 39 | ./service/fail2ban.nix 40 | ./service/radicale.nix 41 | ./service/gpg.nix 42 | ./service/jank-license.nix 43 | ./service/upload.jeaye.com-tmp.nix 44 | ./service/wordy-word.nix 45 | ./service/rainloop.nix 46 | #./service/taskserver.nix 47 | 48 | #./container/nextcloud.nix 49 | ]; 50 | 51 | networking.hostName = "nixums"; 52 | system.stateVersion = "19.03"; 53 | } 54 | -------------------------------------------------------------------------------- /server/container/nextcloud.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | # TODO: Update script, like rainloop has 4 | 5 | # TODO: Harden 6 | # - Disable previews (requires automatic php parsing) 7 | 8 | with import ../util/http.nix {}; 9 | 10 | let 11 | hostAddr = "192.168.255.1"; 12 | localAddr = "192.168.254.1"; 13 | in 14 | { 15 | containers.nextcloud = 16 | { 17 | autoStart = true; 18 | privateNetwork = true; 19 | hostAddress = hostAddr; 20 | localAddress = localAddr; 21 | 22 | # Used for crypto 23 | allowedDevices = [ { modifier = "r"; node = "/dev/urandom"; } ]; 24 | 25 | config = { config, pkgs, ... }: 26 | { 27 | # TODO: Share with host and bring in pam limits config 28 | security.sudo = 29 | { 30 | enable = false; 31 | wheelNeedsPassword = true; 32 | }; 33 | 34 | # TODO: Share with host 35 | i18n = 36 | { 37 | consoleFont = "Lat2-Terminus16"; 38 | consoleKeyMap = "us"; 39 | defaultLocale = "en_US.UTF-8"; 40 | }; 41 | time.timeZone = "America/Los_Angeles"; 42 | 43 | networking.firewall.enable = false; 44 | 45 | services.httpd = 46 | util.http.defaults // { 47 | enable = true; 48 | enablePHP = true; 49 | 50 | # TODO: Bring in redis module 51 | extraModules = 52 | [ 53 | "http2" "rewrite" "headers" "env" "dir" "mime" 54 | ]; 55 | 56 | hostName = "cloud.pastespace.org"; 57 | documentRoot = "/etc/user/http/cloud.pastespace.org"; 58 | extraConfig = util.http.defaults.extraConfig + 59 | '' 60 | 61 | DirectoryIndex index.php 62 | Options -Indexes +FollowSymLinks +ExecCGI 63 | AllowOverride All 64 | Order deny,allow 65 | Allow from all 66 | Require all granted 67 | 68 | Options +FollowSymlinks 69 | AllowOverride All 70 | 71 | 72 | Dav off 73 | 74 | 75 | SetEnv HOME /etc/user/http/cloud.pastespace.org/latest 76 | SetEnv HTTP_HOME /etc/user/http/cloud.pastespace.org/latest 77 | 78 | 79 | Options -Indexes 80 | 81 | 82 | 83 | Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains" 84 | 85 | ''; 86 | 87 | phpOptions = 88 | '' 89 | zend_extension = ${pkgs.php}/lib/php/extensions/opcache.so 90 | opcache.enable = 1 91 | opcache.enable_cli = 1 92 | opcache.interned_strings_buffer = 8 93 | opcache.max_accelerated_files = 10000 94 | opcache.memory_consumption = 128 95 | opcache.save_comments = 1 96 | opcache.revalidate_freq = 1 97 | 98 | max_input_time = 60 99 | max_execution_time = 60 100 | ''; 101 | }; 102 | 103 | users.users.http = 104 | { 105 | isNormalUser = true; 106 | home = "/etc/user/http"; 107 | createHome = true; 108 | }; 109 | 110 | services.cron.systemCronJobs = 111 | [ 112 | "*/15 * * * * http ${pkgs.php}/bin/php -f /etc/user/http/cloud.pastespace.org/latest/cron.php" 113 | ]; 114 | 115 | # TODO: Automatically add config for enabling redis on NextCloud 116 | services.redis = 117 | { 118 | enable = true; 119 | bind = "127.0.0.1"; 120 | #port = 0; 121 | #unixSocket = "/tmp/redis.sock"; 122 | #package = pkgs.redisPhp7; 123 | extraConfig = 124 | '' 125 | #unixsocketperm 755 126 | maxclients 500 127 | ''; 128 | }; 129 | 130 | # TODO: Move to container util 131 | system.activationScripts = 132 | { 133 | homes = 134 | { 135 | deps = []; 136 | text = (builtins.foldl' 137 | (us: u: 138 | '' 139 | ${us} 140 | chown -R ${u.name}:users /etc/user/${u.name} 141 | '') 142 | '' 143 | chmod a+rx /etc/user 144 | '' 145 | (builtins.filter (u: u.isNormalUser) 146 | (map (key: builtins.getAttr key config.users.users) 147 | (builtins.attrNames config.users.users)))); 148 | }; 149 | }; 150 | 151 | environment.etc = 152 | { 153 | "user/http/cloud.pastespace.org/.well-known/.manage-directory".text = ""; 154 | }; 155 | 156 | services.mysql = 157 | { 158 | enable = true; 159 | package = pkgs.mysql; 160 | dataDir = "/var/db/mysql"; 161 | }; 162 | }; 163 | }; 164 | 165 | services.httpd = 166 | { 167 | virtualHosts = 168 | [ 169 | #{ 170 | # hostName = "cloud.pastespace.org"; 171 | # globalRedirect = "https://cloud.pastespace.org/"; 172 | # enableSSL = false; 173 | #} 174 | { 175 | hostName = "cloud.pastespace.org"; 176 | documentRoot = "/etc/user/http/cloud.pastespace.org"; 177 | extraConfig = 178 | '' 179 | #SSLProxyEngine On 180 | ProxyPreserveHost Off 181 | ProxyPass /.well-known ! 182 | ProxyPass /latest/ http://nextcloud.containers/latest/ 183 | ProxyPassReverse /latest/ http://nextcloud.containers/latest/ 184 | ''; # TODO + (defaults "cloud.pastespace.org" "cloud.pastespace.org"); 185 | enableSSL = false; 186 | } 187 | ]; 188 | }; 189 | 190 | environment.etc = 191 | { 192 | "user/http/cloud.pastespace.org/.well-known/.manage-directory".text = ""; 193 | }; 194 | } 195 | -------------------------------------------------------------------------------- /server/pkg/jank-benchmark.nix: -------------------------------------------------------------------------------- 1 | { stdenv, pkgs, fetchgit }: 2 | 3 | stdenv.mkDerivation rec 4 | { 5 | name = "jank-benchmark"; 6 | src = fetchgit 7 | { 8 | url = "https://github.com/jeaye/jank-benchmark.git"; 9 | deepClone = true; 10 | rev = "8262346a1e178a81640f564a8be835c83357e443"; 11 | sha256 = "18bfagp15cwrh3a5gd5ww74lrdgrn0zknvcxdbr7hz999hi5h6cf"; 12 | }; 13 | buildInputs = [ pkgs.leiningen ]; 14 | buildPhase = 15 | '' 16 | # For leiningen 17 | export HOME=$PWD 18 | export LEIN_HOME=$HOME/.lein 19 | mkdir -p $LEIN_HOME 20 | echo "{:user {:local-repo \"$LEIN_HOME\"}}" > $LEIN_HOME/profiles.clj 21 | 22 | ${pkgs.leiningen}/bin/lein uberjar 23 | ''; 24 | installPhase = 25 | '' 26 | mkdir -p $out/{bin,share} 27 | install -m 0644 target/jank-benchmark.jar $out/bin/ 28 | ''; 29 | } 30 | -------------------------------------------------------------------------------- /server/pkg/safepaste.nix: -------------------------------------------------------------------------------- 1 | { stdenv, pkgs, fetchgit }: 2 | 3 | stdenv.mkDerivation rec 4 | { 5 | name = "safepaste"; 6 | src = fetchgit 7 | { 8 | url = "https://github.com/jeaye/safepaste.git"; 9 | deepClone = true; 10 | rev = "0593b68f1d0fb2b41ea14b026bcde4d662c1dbb4"; 11 | sha256 = "1dry2gqmc507jgnp7y0llml9s9mmqzimk75rw8gmxqf79j0jwhnp"; 12 | }; 13 | buildInputs = [ pkgs.boot pkgs.nodejs ]; 14 | buildPhase = 15 | '' 16 | # For leiningen 17 | export HOME=$PWD 18 | export LEIN_HOME=$HOME/.lein 19 | mkdir -p $LEIN_HOME 20 | echo "{:user {:local-repo \"$LEIN_HOME\"}}" > $LEIN_HOME/profiles.clj 21 | 22 | ./bin/package 23 | ''; 24 | installPhase = 25 | '' 26 | mkdir -p $out/{bin,share} 27 | install -m 0644 target/safepaste-standalone.jar $out/bin/ 28 | install -m 0755 tool/clean-expired $out/bin/ 29 | install -m 0755 tool/encrypt $out/bin/ 30 | install -m 0755 tool/ban $out/bin/ 31 | install -m 0644 src/paste/about $out/share/ 32 | ''; 33 | } 34 | -------------------------------------------------------------------------------- /server/pkg/wordy-word.nix: -------------------------------------------------------------------------------- 1 | { stdenv, pkgs, fetchgit }: 2 | 3 | stdenv.mkDerivation rec 4 | { 5 | name = "wordy-word"; 6 | src = fetchgit 7 | { 8 | url = "https://github.com/jeaye/wordy-word.git"; 9 | deepClone = true; 10 | rev = "b771814d1dc5a1c7009cd587d67d73941d59d8d3"; 11 | sha256 = "01xydzy6jabgdapcdq3zaz00l1wbia7g6gz83snlqf863xgfqiap"; 12 | }; 13 | buildInputs = [ pkgs.leiningen pkgs.wget ]; 14 | buildPhase = 15 | '' 16 | # For leiningen 17 | export HOME=$PWD 18 | export LEIN_HOME=$HOME/.lein 19 | mkdir -p $LEIN_HOME 20 | echo "{:user {:local-repo \"$LEIN_HOME\"}}" > $LEIN_HOME/profiles.clj 21 | 22 | ${pkgs.leiningen}/bin/lein uberjar 23 | ''; 24 | installPhase = 25 | '' 26 | mkdir -p $out/{bin,share} 27 | install -m 0644 target/uberjar/wordy-word-0.1.0-SNAPSHOT-standalone.jar $out/bin/wordy-word.jar 28 | install build-word-lists $out/bin/ 29 | ''; 30 | } 31 | -------------------------------------------------------------------------------- /server/program/admin.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | # Some helpful scripts and packages for diagnostics 5 | environment.systemPackages = with pkgs; 6 | [ 7 | pcre 8 | ]; 9 | 10 | # TODO: Add a script for watching failed email logins 11 | # TODO: Script for daily emails sent/recieved per user 12 | environment.etc = 13 | { 14 | "admin/daily-failed-ssh-logins" = 15 | { 16 | text = 17 | '' 18 | #!/run/current-system/sw/bin/bash 19 | set -eu 20 | 21 | title="Failed SSH logins" 22 | printf "%*s\n\n" $(((''${#title}+$COLUMNS)/2)) "$title" 23 | journalctl -u sshd | grep 'Failed password' \ 24 | | awk '{print $1,$2}' \ 25 | | sort -k 1,1M -k 2n \ 26 | | uniq -c \ 27 | | sed -e 's/^\s\+//g' \ 28 | -e 's/\(\S\+\) \+\(\S\+\) \+\(\S\+\)/\2 \3\t\t= \1/' 29 | ''; 30 | mode = "0774"; 31 | }; 32 | "admin/daily-succeeded-ssh-logins" = 33 | { 34 | text = 35 | '' 36 | #!/run/current-system/sw/bin/bash 37 | set -eu 38 | 39 | title="Accepted SSH logins" 40 | printf "%*s\n\n" $(((''${#title}+$COLUMNS)/2)) "$title" 41 | journalctl -u sshd \ 42 | | grep 'Accepted' \ 43 | | sed 's/\(\S\+\) \(\S\+\).*for \(\S\+\) from.*/\1 \2 \3/' \ 44 | | uniq \ 45 | | tr '\n' '|' \ 46 | | sed -e ':loop' \ 47 | -e 's/\(\S\+\) \(\S\+\) \(.\+\)|\1 \2 \(\S\+\)/\1 \2 \3 \4/g' \ 48 | -e 't loop' \ 49 | | tr '|' '\n' \ 50 | | sed -e 's/\(\S\+\) \+\(\S\+\) \+\(.\+\)/\1 \2\t\t= \3/' 51 | ''; 52 | mode = "0774"; 53 | }; 54 | "admin/daily-port-scans" = 55 | { 56 | text = 57 | '' 58 | #!/run/current-system/sw/bin/bash 59 | set -eu 60 | 61 | title="Port scans detected" 62 | printf "%*s\n\n" $(((''${#title}+$COLUMNS)/2)) "$title" 63 | journalctl | grep 'rejected connection:' \ 64 | | awk '{print $1,$2}' \ 65 | | sort -k 1,1M -k 2n \ 66 | | uniq -c \ 67 | | sed -e 's/^\s\+//g' \ 68 | -e 's/\(\S\+\) \+\(\S\+\) \+\(\S\+\)/\2 \3\t\t= \1/' 69 | ''; 70 | mode = "0774"; 71 | }; 72 | "admin/daily-postfix-dos" = 73 | { 74 | text = 75 | '' 76 | #!/run/current-system/sw/bin/bash 77 | set -eu 78 | 79 | title="Postfix DOS attempts" 80 | printf "%*s\n\n" $(((''${#title}+$COLUMNS)/2)) "$title" 81 | journalctl -u postfix | grep 'lost connection after EHLO from' \ 82 | | awk '{print $1,$2}' \ 83 | | sort -k 1,1M -k 2n \ 84 | | uniq -c \ 85 | | sed -e 's/^\s\+//g' \ 86 | -e 's/\(\S\+\) \+\(\S\+\) \+\(\S\+\)/\2 \3\t\t= \1/' 87 | ''; 88 | mode = "0774"; 89 | }; 90 | "admin/rejected-emails" = 91 | { 92 | text = 93 | '' 94 | #!/run/current-system/sw/bin/bash 95 | set -eu 96 | 97 | title="Rejected emails" 98 | printf "%*s\n\n" $(((''${#title}+$COLUMNS)/2)) "$title" 99 | 100 | regex="reject: .+\[(.+)\]: .+ (from=<.+>) (to=<.+>) .+ (helo=<.+>).*" 101 | rejected=$(journalctl -u postfix \ 102 | | pcregrep -o1 -o2 -o3 --om-separator '|' "$regex") 103 | count=$(wc -l <<< "$rejected") 104 | unique=$(sort -u <<< "$rejected" | wc -l) 105 | last=$(sed 's/|/\n\t/g' <<< "$rejected" | tail -15) 106 | 107 | printf "Total: $count\nUnique: $unique\n\n$last\n" 108 | ''; 109 | mode = "0774"; 110 | }; 111 | "admin/daily-valid-safepaste" = 112 | { 113 | text = 114 | '' 115 | #!/run/current-system/sw/bin/bash 116 | set -eu 117 | 118 | title="Valid safepaste submissions" 119 | printf "%*s\n\n" $(((''${#title}+$COLUMNS)/2)) "$title" 120 | journalctl -u safepaste | egrep 'Paste from .+ for .+ is valid.' \ 121 | | awk '{print $1,$2}' \ 122 | | sort -k 1,1M -k 2n \ 123 | | uniq -c \ 124 | | sed -e 's/^\s\+//g' \ 125 | -e 's/\(\S\+\) \+\(\S\+\) \+\(\S\+\)/\2 \3\t\t= \1/' \ 126 | | tail -5 127 | ''; 128 | mode = "0774"; 129 | }; 130 | "admin/monthly-http-access" = 131 | { 132 | text = 133 | '' 134 | #!/run/current-system/sw/bin/bash 135 | set -eu 136 | 137 | month=$1 # Mar, Jun, etc 138 | site=$2 # jeaye.com, safepaste.org, etc 139 | year=$(date +"%Y") 140 | 141 | views=$(grep "$month/$year" /var/log/httpd/access_log-$site \ 142 | | pcregrep -o1 "GET (\/|\/\S*\/)(?:\?.*)? HTTP\/\S+\" 200" \ 143 | | egrep -v "\.(css|png|js|txt|xml|well-known)" \ 144 | | wc -l) 145 | 146 | printf "$month $year $site : $views\n" 147 | ''; 148 | mode = "0774"; 149 | }; 150 | "admin/monthly-http-favorites" = 151 | { 152 | text = 153 | '' 154 | #!/run/current-system/sw/bin/bash 155 | set -eu 156 | 157 | month=$1 # Mar, Jun, etc 158 | site=$2 # jeaye.com, safepaste.org, etc 159 | year=$(date +"%Y") 160 | 161 | views=$(grep "$month/$year" /var/log/httpd/access_log-$site \ 162 | | pcregrep -o1 "GET (\/|\/\S*\/)(?:\?.*)? HTTP\/\S+\" 200" \ 163 | | egrep -v "\.(css|png|js|txt|xml|well-known)" \ 164 | | sort \ 165 | | uniq -c \ 166 | | sort -n) 167 | 168 | echo "$month $year $site :" 169 | echo "$views" 170 | ''; 171 | mode = "0774"; 172 | }; 173 | "admin/unban-fail2ban-ip" = 174 | { 175 | text = 176 | '' 177 | #!/run/current-system/sw/bin/bash 178 | set -eu 179 | 180 | jails=$(fail2ban-client status | pcregrep -o1 "list:\s*(\w.*)" | sed 's/,//g') 181 | for jail in $jails; 182 | do 183 | echo "Removing $1 from $jail" 184 | fail2ban-client set $jail unbanip $1 > /dev/null 2>&1 || true 185 | done 186 | ''; 187 | mode = "0774"; 188 | }; 189 | }; 190 | } 191 | -------------------------------------------------------------------------------- /server/program/essential.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | environment.systemPackages = with pkgs; 5 | [ 6 | vim 7 | wget 8 | elinks 9 | unzip 10 | git 11 | htop 12 | #bashCompletion 13 | telnet 14 | traceroute 15 | nix-repl 16 | file 17 | ]; 18 | } 19 | -------------------------------------------------------------------------------- /server/service/acme.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | with import ../util/acme.nix {}; 4 | 5 | let 6 | global-email = "contact@jeaye.com"; 7 | in 8 | { 9 | environment.systemPackages = [ pkgs.simp_le ]; 10 | 11 | security.acme = 12 | { 13 | directory = util.acme.directory; 14 | 15 | # TODO: Combine these subdomains where possible 16 | certs = 17 | { 18 | "pastespace.org" = 19 | { 20 | webroot = "/etc/user/http/pastespace.org"; 21 | extraDomains = 22 | { 23 | "www.pastespace.org" = null; 24 | "mail.pastespace.org" = null; 25 | #"cloud.pastespace.org:/etc/user/http/cloud.pastespace.org" = null; 26 | "webmail.pastespace.org:/etc/user/http/webmail.pastespace.org" = null; 27 | }; 28 | email = global-email; 29 | plugins = util.acme.plugins; 30 | postRun = util.acme.post-run + "systemctl restart dovecot2;"; 31 | }; 32 | "safepaste.org" = 33 | { 34 | webroot = "/etc/user/http/safepaste.org"; 35 | extraDomains = 36 | { 37 | "www.safepaste.org" = null; 38 | }; 39 | email = global-email; 40 | plugins = util.acme.plugins; 41 | postRun = util.acme.post-run; 42 | }; 43 | "jeaye.com" = 44 | { 45 | webroot = "/etc/user/http/jeaye.com"; 46 | extraDomains = 47 | { "www.jeaye.com" = null; }; 48 | email = global-email; 49 | plugins = util.acme.plugins; 50 | postRun = util.acme.post-run; 51 | }; 52 | "upload.jeaye.com" = 53 | { 54 | webroot = "/etc/user/http/upload.jeaye.com"; 55 | extraDomains = 56 | { "upload.jeaye.com" = null; }; 57 | email = global-email; 58 | plugins = util.acme.plugins; 59 | postRun = util.acme.post-run; 60 | }; 61 | "jank-lang.org" = 62 | { 63 | webroot = "/etc/user/http/jank-lang.org"; 64 | extraDomains = 65 | { 66 | "www.jank-lang.org" = null; 67 | "bench.jank-lang.org" = null; 68 | }; 69 | email = global-email; 70 | plugins = util.acme.plugins; 71 | postRun = util.acme.post-run; 72 | }; 73 | "fu-er.com" = 74 | { 75 | webroot = "/etc/user/http/fu-er.com"; 76 | extraDomains = 77 | { 78 | "www.fu-er.com" = null; 79 | }; 80 | email = global-email; 81 | plugins = util.acme.plugins; 82 | postRun = util.acme.post-run; 83 | }; 84 | "penelope-art.com" = 85 | { 86 | webroot = "/etc/user/http/penelope-art.com"; 87 | extraDomains = 88 | { 89 | "www.penelope-art.com" = null; 90 | }; 91 | email = global-email; 92 | plugins = util.acme.plugins; 93 | postRun = util.acme.post-run; 94 | }; 95 | "penny-art.com" = 96 | { 97 | webroot = "/etc/user/http/penny-art.com"; 98 | extraDomains = 99 | { 100 | "www.penny-art.com" = null; 101 | }; 102 | email = global-email; 103 | plugins = util.acme.plugins; 104 | postRun = util.acme.post-run; 105 | }; 106 | }; 107 | }; 108 | } 109 | -------------------------------------------------------------------------------- /server/service/data/park-index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | %%domain%% is for sale 8 | 9 | 10 | 69 | 93 | 94 | 95 | 96 |
97 |
98 |
%%domain%%
99 |
This domain is for sale.
100 | 101 |
102 |
103 | 104 | 105 | -------------------------------------------------------------------------------- /server/service/data/upgrade-rainloop: -------------------------------------------------------------------------------- 1 | #!/run/current-system/sw/bin/bash 2 | 3 | set -eu -o pipefail 4 | 5 | zip_file=rainloop-community-latest.zip 6 | signature_file=$zip_file.asc 7 | remote_webmail=https://www.rainloop.net/repository/webmail 8 | local_webmail=/etc/user/http/webmail.pastespace.org 9 | 10 | printf "RainLoop: checking for upgrades... " 11 | new_zip_signature=$(curl -s "$remote_webmail/$signature_file" || true) 12 | old_zip_signature=$(cat "$local_webmail/latest/$signature_file" || true) 13 | 14 | if [ "x$new_zip_signature" == "x" ]; 15 | then 16 | echo "no internet" 17 | exit 0 18 | fi 19 | 20 | if [ "$new_zip_signature" != "$old_zip_signature" ]; 21 | then 22 | echo "found" 23 | echo "RainLoop: upgrading..." 24 | temp_dir=$(mktemp -d) 25 | pushd "$temp_dir" 26 | gpg2 --import <(curl -s "https://www.rainloop.net/repository/RainLoop.asc") 27 | 28 | # Download new version 29 | wget "$remote_webmail/$zip_file" 30 | gpg2 --verify <(echo "$new_zip_signature") "$zip_file" 31 | 32 | # Start from the latest, if it's there 33 | if [ -d "$local_webmail/latest" ]; 34 | then 35 | rsync -av "$local_webmail/latest/" . 36 | fi 37 | 38 | unzip -o "$zip_file" 39 | rm "$zip_file" 40 | 41 | echo "$new_zip_signature" > "$signature_file" 42 | popd 43 | 44 | new_version=$(date +'version-%Y-%m-%d.%H:%M:%S') 45 | new_path=$local_webmail/$new_version 46 | if [ -d "$new_path" ]; 47 | then 48 | echo "RainLoop: directory already exists: $new_path" 49 | exit 1 50 | fi 51 | 52 | # Move the new version into place and setup permissions 53 | mv "$temp_dir" "$new_path" 54 | find "$new_path" -type d -exec chmod 755 {} \; 55 | find "$new_path" -type f -exec chmod 644 {} \; 56 | chown -R http:users "$new_path" 57 | 58 | # Atomically link/upgrade 59 | ln -sfn "$new_path" "$local_webmail/latest" 60 | 61 | echo "Rainloop: upgrade complete" 62 | else 63 | echo "not found" 64 | fi 65 | -------------------------------------------------------------------------------- /server/service/domain-parking.nix: -------------------------------------------------------------------------------- 1 | { lib, config, pkgs, ... }: 2 | 3 | let 4 | domains = 5 | [ 6 | "anonymust.org" 7 | "anylist.io" 8 | "autocoupon.org" 9 | "bankapp.io" 10 | "candycapitalist.com" 11 | "candycapitalist.org" 12 | "clojure-atlas.org" 13 | "cpp-atlas.org" 14 | "date-ver.org" 15 | "datever.org" 16 | "discipline-lang.com" 17 | "discipline-lang.org" 18 | "discipline.sh" 19 | "farmware.io" 20 | "furthington.com" 21 | "helderman.io" 22 | "history-proxy.org" 23 | "idiolect.org" 24 | "idiolisp.com" 25 | "idiolisp.io" 26 | "idiolisp.org" 27 | "jank-platform.org" 28 | "jank.wiki" 29 | "jeaye.dev" 30 | "jeaye.io" 31 | "orthodox-lang.com" 32 | "orthodox-lang.io" 33 | "orthodox-lang.org" 34 | "penny.cafe" 35 | "penny.ink" 36 | "penny.poker" 37 | "penny.works" 38 | "penny.wtf" 39 | "polyvore.io" 40 | "preplist.io" 41 | "preplist.org" 42 | "puretorrent.org" 43 | "safetybox.org" 44 | "spamcan.org" 45 | "text-box.org" 46 | "texta.io" 47 | "trustcoin.org" 48 | "tunnelvpn.io" 49 | "tunnelvpn.org" 50 | "univps.org" 51 | "unorthodox-lang.com" 52 | "unorthodox-lang.io" 53 | "unorthodox-lang.org" 54 | "unorthodox.io" 55 | "vingtsun.io" 56 | "wingtsun.io" 57 | "zenlock.io" 58 | "zenlock.org" 59 | "zentrain.io" 60 | ]; 61 | makeVirtualHost = domain: 62 | (builtins.nameValuePair domain { 63 | serverAliases = [("www." + domain)]; 64 | enableSSL = false; 65 | documentRoot = "/etc/user/http/" + domain; 66 | }); 67 | index = builtins.readFile ./data/park-index.html; 68 | makeIndexFile = domain: 69 | { 70 | name = "user/http/" + domain + "/index.html"; 71 | value = 72 | { 73 | text = builtins.replaceStrings ["%%domain%%"] [domain] index; 74 | }; 75 | }; 76 | in 77 | { 78 | services.httpd.virtualHosts = (builtins.listToAttrs (map makeVirtualHost domains)); 79 | environment.etc = (builtins.listToAttrs (map makeIndexFile domains)); 80 | } 81 | -------------------------------------------------------------------------------- /server/service/dovecot.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | services.dovecot2 = 5 | { 6 | enable = true; 7 | enableImap = true; 8 | enablePop3 = false; 9 | mailLocation = "maildir:~/Maildir"; 10 | sslServerCert = "/var/lib/acme/pastespace.org/cert.pem"; 11 | sslServerKey = "/var/lib/acme/pastespace.org/key.pem"; 12 | sslCACert = "/var/lib/acme/pastespace.org/chain.pem"; 13 | extraConfig = 14 | '' 15 | ssl = required 16 | 17 | protocol imap { 18 | mail_plugins = $mail_plugins autocreate 19 | } 20 | 21 | # TODO: Update to namespaces 22 | plugin { 23 | autocreate = Trash 24 | autocreate2 = Sent 25 | autocreate3 = Drafts 26 | autocreate4 = Spam 27 | autosubscribe = Trash 28 | autosubscribe2 = Sent 29 | autosubscribe3 = Drafts 30 | autosubscribe4 = Spam 31 | } 32 | 33 | service auth { 34 | unix_listener /var/lib/postfix/queue/private/auth { 35 | mode = 0660 36 | user = postfix 37 | group = postfix 38 | } 39 | } 40 | ''; 41 | }; 42 | 43 | networking.firewall = 44 | { 45 | allowedTCPPorts = 46 | [ 47 | 143 # imap 48 | 993 # imap 49 | ]; 50 | }; 51 | } 52 | -------------------------------------------------------------------------------- /server/service/fail2ban.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | nixpkgs.config = 5 | { 6 | packageOverrides = pkgs: rec 7 | { 8 | fail2ban = pkgs.fail2ban.overrideDerivation (oldAttrs : 9 | { 10 | src = pkgs.fetchzip 11 | { 12 | name = "fail2ban-0.9.3-src"; 13 | url = "https://github.com/fail2ban/fail2ban/archive/0.9.3.tar.gz"; 14 | sha256 = "1pwgr56i6l6wh2ap8b5vknxgsscfzjqy2nmd1c3vzdii5kf72j0f"; 15 | }; 16 | }); 17 | }; 18 | }; 19 | 20 | services.fail2ban = 21 | { 22 | enable = true; 23 | 24 | jails.DEFAULT = 25 | '' 26 | bantime = 3600 27 | ''; 28 | jails.sshd = 29 | '' 30 | filter = sshd 31 | maxretry = 4 32 | action = iptables[name=ssh, port=ssh, protocol=tcp] 33 | enabled = true 34 | ''; 35 | jails.sshd-ddos = 36 | '' 37 | filter = sshd-ddos 38 | maxretry = 2 39 | action = iptables[name=ssh, port=ssh, protocol=tcp] 40 | enabled = true 41 | ''; 42 | jails.port-scan = 43 | '' 44 | filter = port-scan 45 | action = iptables-allports[name=port-scan] 46 | maxretry = 2 47 | bantime = 7200 48 | enabled = true 49 | ''; 50 | # TODO: Move these to their appropriate files 51 | jails.postfix = 52 | '' 53 | filter = postfix 54 | maxretry = 3 55 | action = iptables[name=postfix, port=smtp, protocol=tcp] 56 | enabled = false 57 | ''; 58 | jails.postfix-sasl = 59 | '' 60 | filter = postfix-sasl 61 | maxretry = 3 62 | action = iptables[name=postfix, port=smtp, protocol=tcp] 63 | enabled = true 64 | ''; 65 | jails.postfix-custom = 66 | '' 67 | filter = postfix-custom 68 | maxretry = 3 69 | action = iptables[name=postfix, port=submission, protocol=tcp] 70 | iptables[name=postfix, port=smtp, protocol=tcp] 71 | bantime = 7200 72 | enabled = true 73 | ''; 74 | }; 75 | environment.etc."fail2ban/filter.d/port-scan.conf".text = 76 | '' 77 | [Definition] 78 | failregex = rejected connection: .* SRC= 79 | ''; 80 | environment.etc."fail2ban/filter.d/postfix-custom.conf".text = 81 | '' 82 | [Definition] 83 | failregex = lost connection after (EHLO|AUTH) from \S+\[\] 84 | reject: RCPT from \S+\[\]: 450 4.7.1 85 | reject: RCPT from \S+\[\]: 554 5\.7\.1 86 | reject: VRFY from \S+\[\]: 550 5\.1\.1 87 | improper command pipelining after \S+ from [^[]*\[\]:? 88 | ''; 89 | 90 | # Limit stack size to reduce memory usage 91 | systemd.services.fail2ban.serviceConfig.LimitSTACK = 256 * 1024; 92 | } 93 | -------------------------------------------------------------------------------- /server/service/gpg.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | # Refresh keys daily 5 | services.cron.systemCronJobs = 6 | [ 7 | "0 23 * * * jeaye /etc/user/jeaye/bin/gpg --refresh-keys > /dev/null" 8 | ]; 9 | 10 | # XXX: We need to import the private key 11 | environment.etc."user/http/upload.jeaye.com/6C61E510.asc".text = 12 | ''-----BEGIN PGP PUBLIC KEY BLOCK----- 13 | Version: GnuPG v2 14 | 15 | mQENBFaWCMYBCAChLz9/nVXLdrNIhvHD4Kg4DOxTp7XaEXEVM9oKTnxbO49ZKl9u 16 | 2tuKaRtyL23BBfKtpm7dBkjBQDOyX4+92PxSlJgB0UC169jExRNfqU2b65bvNHzS 17 | 2jzRsuJ/B6u+FmaMGGXuv1UItWxlnD7c5aD1WdpthcewiED2SLCcp2fw5rNv6gw1 18 | uvEzRO+x6SAzmRcoDQF49Dd6U68z9X+c74n1HAKnQT5/l4ftZh/MK6/VbiGMHWbF 19 | I5U7/AtYQAJC4yFf6nmJb4Z7RiaGyiLyBdj1gW1de/a1YwJcGMTrpOnZa0ZxCwgE 20 | S63/hNs23AFI1dSpG3aEYDOkCe8iYB5nlzyFABEBAAG0GUplYXllIDxjb250YWN0 21 | QGplYXllLmNvbT6JATcEEwEIACEFAlaWCMYCGwMFCwkIBwIGFQgJCgsCBBYCAwEC 22 | HgECF4AACgkQp3/8hWxh5RDf1Af+PYhJ/w/mFbkE/BH1r6zOVA8o+ikTxTvGcKZo 23 | hiiJ6vPfaI1fUsPnwY/E6o6xz13OOHtvhb2844v4fc8Q1mOo6KQbjbU+HC/M4R6u 24 | DT1vwgvGftJSFAkV9cpVcdxK9/dCCXLudD17Lt4xPjLSdi1ntdlEWX5izlhjb/El 25 | /uY7OWJ/aa1f9DM8tTVE7kaOTtre5zx+ojZQJnl60CzFP2OTlQunE52r5ZBPEsIu 26 | rf2LUh2oEQNE6g5wQ7QTinE8Jp/n/Ibeuw3GdFSeRo7IRVdSsxKEi6nb2Elzs1nv 27 | CjWCML0LqXJDMkNCLX5Q86tx818lkFgblBU4Xi6y5yFNwRgn8LQeSmVheWUgPGNv 28 | bnRhY3RAcGFzdGVzcGFjZS5vcmc+iQE3BBMBCAAhBQJWliJnAhsDBQsJCAcCBhUI 29 | CQoLAgQWAgMBAh4BAheAAAoJEKd//IVsYeUQ7v4H/19Vu/HoE0rYyf8FY79oFT3D 30 | aoAjXZbGfLqJPso7FqteiI9nGjv0H7ZUfOWOxlPankItVBCAkx0bDQ3LaZAtP+Uv 31 | uCzqNB8+bOwO7maKy0aJVi/esDXzG1OnGww1jF2G4wkclNpRptnRgU5EKH2mlpSV 32 | SxX+zuxQ+BsMOux0it07HNfO9tazeyHl4xShf24XuSWeKXETbC0TK1MY+EDKpVyp 33 | EKJkzhzdF1RL7/aF8eVobW7EWCnyr/Ph0+68HWTcolReNXDouWJff1FLjqsuXqXF 34 | scLaMl3u136NIA9VpJOzm/Lm287uECr75nHZy2Li90RTRBPxKeYNoVCQq+1Kn4m5 35 | AQ0EVpYIxgEIAL+kj13aMEYXOTsunr7uU55OwlxdiV2Yo7GmnORj4Gezq5a6CZYz 36 | Z8CXkwHsVy4Q9KBPxPUr1h1UasA2DLG20vdoxhHrmZFiGAKauq7aghLMVfFv3q9Z 37 | cWrj9J0EqQGr+m/dcuBfCxlIfXgu3NJJK2gej+HsIBq4U5JpMJFqN5faUzOPjusT 38 | mAgNgQrsLKP5QchghlgM6cueS0O+PJ5GuSNQvJ6bDlfNsow43DohuDWlQsfpbQYL 39 | pveCGmpCM2UHzbIregPsKJEVSvk2kC6izmepEiinNBffhfxBVEY07Tg+aMbUtbVI 40 | Cjp7ufdi5HGLYUUO3vUT94g0UVROmnCSjL0AEQEAAYkBHwQYAQgACQUCVpYIxgIb 41 | DAAKCRCnf/yFbGHlEBwnB/0cMpUnaxHZpn9AVSkSbwF+3v0t5fa0F/Z5wATqU0eT 42 | 9TR9a4Grsh9dpLUJ634yryA/aaQBxdJ4s8NK8h8VDDKEb86PdfWTU6psXvHG7yfH 43 | o11+onQitAj7BHZyp6b6q10XOfW6tiT3cVAFhUMYPWhDqv1Oq44MB60MZmt7sQFc 44 | EKQIyGau+FdcKfN6IIufUveq/uYXT9YuFbEd2k774LusCf8tBqJ+9ehy9YeUSxBl 45 | tkz7tldLlyD9v0N5TSBPm2T0wI6Ih30HA05v/vAdGXovxBJI7kLQ6Z7aPBDxFQX1 46 | ac4UGQmr6bAUue97EAZkpmONhTW6szTM+PTNAFQ2HmsT 47 | =j3xc 48 | -----END PGP PUBLIC KEY BLOCK-----''; 49 | } 50 | -------------------------------------------------------------------------------- /server/service/httpd.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | with import ../util/http.nix {}; 4 | 5 | { 6 | services.httpd = 7 | util.http.defaults // { 8 | enable = true; 9 | 10 | extraModules = 11 | [ 12 | "http2" "proxy" "proxy_http" 13 | { name = "php7"; path = "${pkgs.php}/modules/libphp7.so"; } 14 | ]; 15 | 16 | # TODO: Add proxy helper fn 17 | virtualHosts = 18 | { 19 | "pastespace.org" = 20 | { 21 | serverAliases = 22 | [ 23 | "www.pastespace.org" 24 | "mail.pastespace.org" 25 | ]; 26 | forceSSL = true; 27 | documentRoot = "/etc/user/http/pastespace.org"; 28 | extraConfig = 29 | '' 30 | # XXX: Requires manual creation using htpasswd 31 | 32 | AuthType Basic 33 | AuthName "Restricted Calendar" 34 | AuthBasicProvider file 35 | AuthUserFile /etc/user/http/calendar-auth-users 36 | Require valid-user 37 | RequestHeader set X-Script-Name "/calendar" 38 | 39 | 40 | RedirectMatch 301 "^\/(?!\.well-known|calendar).*" https://jeaye.com 41 | 42 | SSLProxyEngine On 43 | ProxyPreserveHost Off 44 | ProxyPass /.well-known ! 45 | ProxyPass /calendar http://localhost:5232/ 46 | ProxyPassReverse /calendar http://localhost:5232/ 47 | '' + (util.http.helpers.withSSL "pastespace.org" "pastespace.org"); 48 | enableSSL = true; 49 | } 50 | { 51 | hostName = "webmail.pastespace.org"; 52 | globalRedirect = "https://webmail.pastespace.org/"; 53 | enableSSL = false; 54 | } 55 | { 56 | hostName = "webmail.pastespace.org"; 57 | documentRoot = "/etc/user/http/webmail.pastespace.org"; 58 | extraConfig = 59 | '' 60 | 61 | DirectoryIndex index.php 62 | Options -Indexes +FollowSymLinks +ExecCGI 63 | AllowOverride All 64 | Order deny,allow 65 | Allow from all 66 | Require all granted 67 | 68 | 69 | Options -Indexes 70 | Deny from all 71 | 72 | '' + (util.http.helpers.withSSL "webmail.pastespace.org" "pastespace.org"); 73 | enableSSL = true; 74 | } 75 | { 76 | hostName = "safepaste.org"; 77 | serverAliases = 78 | [ 79 | "www.safepaste.org" 80 | ]; 81 | globalRedirect = "https://safepaste.org/"; 82 | enableSSL = false; 83 | } 84 | { 85 | hostName = "safepaste.org"; 86 | documentRoot = "/etc/user/http/safepaste.org"; 87 | extraConfig = 88 | '' 89 | SSLProxyEngine On 90 | ProxyPreserveHost Off 91 | ProxyPass /.well-known ! 92 | ProxyPass / http://localhost:3000/ 93 | ProxyPassReverse / http://localhost:3000/ 94 | '' + (util.http.helpers.withSSL "safepaste.org" "safepaste.org"); 95 | enableSSL = true; 96 | } 97 | { 98 | hostName = "upload.jeaye.com"; 99 | globalRedirect = "https://upload.jeaye.com/"; 100 | } 101 | { 102 | hostName = "upload.jeaye.com"; 103 | documentRoot = "/etc/user/http/upload.jeaye.com"; 104 | extraConfig = 105 | '' 106 | 107 | Options +Indexes 108 | IndexOptions FancyIndexing SuppressDescription NameWidth=* 109 | 110 | Protocols http/1.1 111 | '' + (util.http.helpers.withSSL "upload.jeaye.com" "upload.jeaye.com"); 112 | enableSSL = true; 113 | } 114 | { 115 | hostName = "jeaye.com"; 116 | serverAliases = [ "www.jeaye.com" ]; 117 | globalRedirect = "https://jeaye.com/"; 118 | } 119 | { 120 | hostName = "jeaye.com"; 121 | serverAliases = [ "www.jeaye.com" ]; 122 | documentRoot = "/etc/user/http/jeaye.com"; 123 | extraConfig = 124 | '' 125 | SSLProxyEngine On 126 | ProxyPreserveHost Off 127 | ProxyPass /.well-known ! 128 | ProxyPass / https://jeaye.github.io/jeaye.com/ 129 | ProxyPassReverse / https://jeaye.github.io/jeaye.com/ 130 | ProxyPassReverse / http://jeaye.github.io/jeaye.com/ 131 | '' + (util.http.helpers.withSSL "jeaye.com" "jeaye.com"); 132 | enableSSL = true; 133 | } 134 | { 135 | hostName = "jank-lang.org"; 136 | serverAliases = [ "www.jank-lang.org" ]; 137 | globalRedirect = "https://jank-lang.org/"; 138 | enableSSL = false; 139 | } 140 | { 141 | hostName = "jank-lang.org"; 142 | serverAliases = [ "www.jank-lang.org" ]; 143 | documentRoot = "/etc/user/http/jank-lang.org"; 144 | extraConfig = 145 | '' 146 | RedirectMatch 301 "^\/(?!\.well-known).*" https://github.com/jeaye/jank 147 | '' + (util.http.helpers.withSSL "jank-lang.org" "jank-lang.org"); 148 | enableSSL = true; 149 | } 150 | { 151 | hostName = "bench.jank-lang.org"; 152 | globalRedirect = "https://bench.jank-lang.org/"; 153 | enableSSL = false; 154 | } 155 | { 156 | hostName = "bench.jank-lang.org"; 157 | documentRoot = "/etc/user/http/jank-lang.org"; 158 | extraConfig = 159 | '' 160 | SSLProxyEngine On 161 | ProxyPreserveHost Off 162 | ProxyPass /.well-known ! 163 | ProxyPass / http://localhost:3001/ 164 | ProxyPassReverse / http://localhost:3001/ 165 | '' + (util.http.helpers.withSSL "jank-lang.org" "jank-lang.org"); 166 | enableSSL = true; 167 | } 168 | { 169 | hostName = "fu-er.com"; 170 | serverAliases = [ "www.fu-er.com" ]; 171 | globalRedirect = "https://fu-er.com/"; 172 | enableSSL = false; 173 | } 174 | { 175 | hostName = "fu-er.com"; 176 | serverAliases = [ "www.fu-er.com" ]; 177 | documentRoot = "/etc/user/http/fu-er.com"; 178 | extraConfig = 179 | '' 180 | '' + (util.http.helpers.withSSL "fu-er.com" "fu-er.com"); 181 | enableSSL = true; 182 | } 183 | { 184 | hostName = "penelope-art.com"; 185 | serverAliases = [ "www.penelope-art.com" ]; 186 | globalRedirect = "https://penelope-art.com/"; 187 | enableSSL = false; 188 | } 189 | { 190 | hostName = "penelope-art.com"; 191 | serverAliases = [ "www.penelope-art.com" ]; 192 | documentRoot = "/etc/user/http/penelope-art.com"; 193 | extraConfig = 194 | '' 195 | DirectoryIndex resume.pdf 196 | '' + (util.http.helpers.withSSL "penelope-art.com" "penelope-art.com"); 197 | enableSSL = true; 198 | } 199 | { 200 | hostName = "penny-art.com"; 201 | serverAliases = [ "www.penny-art.com" ]; 202 | globalRedirect = "https://penny-art.com/"; 203 | enableSSL = false; 204 | } 205 | { 206 | hostName = "penny-art.com"; 207 | serverAliases = [ "www.penny-art.com" ]; 208 | documentRoot = "/etc/user/http/penny-art.com"; 209 | extraConfig = 210 | '' 211 | RedirectMatch 301 "^\/(?!\.well-known).*" https://penny.artstation.com/ 212 | '' + (util.http.helpers.withSSL "penny-art.com" "penny-art.com"); 213 | enableSSL = true; 214 | } 215 | }; 216 | }; 217 | 218 | users.users.http = 219 | { 220 | isNormalUser = true; 221 | home = "/etc/user/http"; 222 | }; 223 | 224 | environment.etc = 225 | { 226 | "user/http/pastespace.org/.well-known/.manage-directory".text = ""; 227 | "user/http/webmail.pastespace.org/.well-known/.manage-directory".text = ""; 228 | "user/http/safepaste.org/.well-known/.manage-directory".text = ""; 229 | "user/http/jeaye.com/.well-known/.manage-directory".text = ""; 230 | "user/http/jank-lang.org/.well-known/.manage-directory".text = ""; 231 | "user/http/upload.jeaye.com/.well-known/.manage-directory".text = ""; 232 | "user/http/upload.jeaye.com/tmp/.manage-directory".text = ""; 233 | "user/http/fu-er.com/.well-known/.manage-directory".text = ""; 234 | "user/http/penelope-art.com/.well-known/.manage-directory".text = ""; 235 | "user/http/penny-art.com/.well-known/.manage-directory".text = ""; 236 | }; 237 | 238 | networking.firewall = 239 | { 240 | allowedTCPPorts = 241 | [ 242 | 80 # http 243 | 443 # https 244 | ]; 245 | }; 246 | } 247 | -------------------------------------------------------------------------------- /server/service/jank-benchmark.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | environment.systemPackages = 5 | [ 6 | pkgs.leiningen 7 | pkgs.openjdk 8 | pkgs.gcc 9 | ]; 10 | 11 | nixpkgs.config = 12 | { 13 | packageOverrides = pkgs: rec 14 | { 15 | jank-benchmark = pkgs.callPackage ../pkg/jank-benchmark.nix { }; 16 | }; 17 | }; 18 | 19 | environment.etc."user/jank-benchmark/run-server" = 20 | { 21 | text = 22 | '' 23 | #!/run/current-system/sw/bin/bash 24 | set -eu 25 | export PATH=${pkgs.git}/bin:${pkgs.leiningen}/bin:${pkgs.gcc}/bin:$PATH 26 | 27 | ${pkgs.openjdk}/bin/java -jar ${pkgs.jank-benchmark}/bin/jank-benchmark.jar 28 | ''; 29 | mode = "0775"; 30 | }; 31 | 32 | systemd.services.jank-benchmark = 33 | { 34 | wantedBy = [ "multi-user.target" ]; 35 | after = [ "network.target" ]; 36 | serviceConfig = 37 | { 38 | User = "jank-benchmark"; 39 | WorkingDirectory = "/etc/user/jank-benchmark"; 40 | ExecStart = "/etc/user/jank-benchmark/run-server"; 41 | }; 42 | }; 43 | 44 | users.users.jank-benchmark = 45 | { 46 | isNormalUser = false; 47 | home = "/etc/user/jank-benchmark"; 48 | createHome = true; 49 | }; 50 | 51 | system.activationScripts = 52 | { 53 | jank-benchmark-home = 54 | { 55 | deps = []; 56 | text = 57 | '' 58 | chown -R jank-benchmark:users /etc/user/jank-benchmark 59 | ''; 60 | }; 61 | }; 62 | 63 | networking.firewall.allowedTCPPorts = [ 3001 ]; 64 | } 65 | -------------------------------------------------------------------------------- /server/service/jank-license.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | environment.etc."user/http/upload.jeaye.com/jank-license".text = 5 | ''Redistribution and use in source and binary forms, with or without 6 | modification, are permitted, free of charge, provided that the following 7 | conditions are met: 8 | 9 | Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | Redistributions in any form must be accompanied by information on how to obtain 17 | complete source code for the distributed software and any accompanying software 18 | that uses the distributed software. The source code must either be included in 19 | the distribution or be available free of charge. For an executable file, 20 | complete source code means the source code for all modules it contains. It does 21 | not include source code for modules or files that typically accompany the major 22 | components of the operating system on which the executable file runs. 23 | 24 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 27 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | SOFTWARE.''; 31 | } 32 | -------------------------------------------------------------------------------- /server/service/opendkim.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | environment.systemPackages = with pkgs; 5 | [ 6 | opendkim 7 | openssl 8 | ]; 9 | 10 | environment.etc = 11 | { 12 | "opendkim/opendkim.conf" = 13 | { 14 | text = 15 | '' 16 | Domain pastespace.org safepaste.org jeaye.com fu-er.com penelope-art.com penny-art.com 17 | Selector mail 18 | KeyTable refile:/etc/opendkim/key-table 19 | SigningTable refile:/etc/opendkim/signing-table 20 | Socket local:/var/run/opendkim/opendkim.sock 21 | ReportAddress postmaster@pastespace.org 22 | RequireSafeKeys False 23 | UserID opendkim:opendkim 24 | 25 | AutoRestart Yes 26 | AutoRestartRate 10/1h 27 | UMask 002 28 | Syslog yes 29 | SyslogSuccess Yes 30 | LogWhy Yes 31 | 32 | Canonicalization relaxed/simple 33 | ''; 34 | }; 35 | "opendkim/key-table" = 36 | { 37 | text = 38 | '' 39 | mail._domainkey.pastespace.org pastespace.org:mail:/etc/opendkim/keys/pastespace.org/mail.private 40 | mail._domainkey.safepaste.org safepaste.org:mail:/etc/opendkim/keys/safepaste.org/mail.private 41 | mail._domainkey.jeaye.com jeaye.com:mail:/etc/opendkim/keys/jeaye.com/mail.private 42 | mail._domainkey.fu-er.com fu-er.com:mail:/etc/opendkim/keys/fu-er.com/mail.private 43 | mail._domainkey.penelope-art.com penelope-art.com:mail:/etc/opendkim/keys/penelope-art.com/mail.private 44 | mail._domainkey.penny-art.com penny-art.com:mail:/etc/opendkim/keys/penny-art.com/mail.private 45 | ''; 46 | }; 47 | "opendkim/signing-table" = 48 | { 49 | text = 50 | '' 51 | *@pastespace.org mail._domainkey.pastespace.org 52 | *@safepaste.org mail._domainkey.safepaste.org 53 | *@jeaye.com mail._domainkey.jeaye.com 54 | *@fu-er.com mail._domainkey.fu-er.com 55 | *@penelope-art.com mail._domainkey.penelope-art.com 56 | *@penny-art.com mail._domainkey.penny-art.com 57 | ''; 58 | }; 59 | }; 60 | 61 | system.activationScripts = 62 | { 63 | opendkim = 64 | { 65 | deps = []; 66 | text = 67 | '' 68 | export PATH=${pkgs.stdenv}/bin:${pkgs.openssl}/bin:${pkgs.gnused}/bin:${pkgs.gnugrep}/bin:$PATH 69 | mkdir -p /var/run/opendkim 70 | chown -R opendkim:opendkim /var/run/opendkim 71 | 72 | work() 73 | { 74 | if [ ! -f /etc/opendkim/keys/$1/mail.private ]; 75 | then 76 | mkdir -p /etc/opendkim/keys/$1 77 | ${pkgs.opendkim}/bin/opendkim-genkey -d $1 -D /etc/opendkim/keys/$1/ -s mail -r -t 78 | fi 79 | } 80 | for domain in pastespace.org safepaste.org jeaye.com fu-er.com penelope-art.com penny-art.com; 81 | do 82 | work $domain 83 | done 84 | 85 | chmod -R 700 /etc/opendkim/keys 86 | chown -R opendkim:opendkim /etc/opendkim/keys 87 | ''; 88 | }; 89 | }; 90 | 91 | systemd.services.opendkim = 92 | { 93 | wantedBy = [ "multi-user.target" ]; 94 | after = [ "network.target" ]; 95 | serviceConfig = 96 | { 97 | ExecStart = 98 | '' 99 | ${pkgs.opendkim}/bin/opendkim -f -x /etc/opendkim/opendkim.conf 100 | ''; 101 | }; 102 | }; 103 | 104 | users.users.opendkim = 105 | { 106 | isSystemUser = true; 107 | extraGroups = [ "opendkim" ]; 108 | }; 109 | users.users.postfix.extraGroups = [ "opendkim" ]; 110 | users.groups.opendkim = {}; 111 | } 112 | -------------------------------------------------------------------------------- /server/service/postfix.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | environment.systemPackages = with pkgs; 5 | [ 6 | procmail 7 | ]; 8 | 9 | services.postfix = rec 10 | { 11 | enable = true; 12 | domain = "pastespace.org"; 13 | hostname = "${domain}"; 14 | origin = "${domain}"; 15 | destination = 16 | [ 17 | "${hostname}" 18 | "${domain}" 19 | "localhost.${domain}" 20 | "localhost" 21 | ]; 22 | networksStyle = "host"; 23 | relayDomains = []; 24 | virtual = 25 | '' 26 | contact@pastespace.org jeaye 27 | domain@pastespace.org jeaye 28 | contact@safepaste.org jeaye 29 | contact@arrownext.com jeaye 30 | contact@jeaye.com jeaye 31 | contact@trustcoin.org jeaye 32 | 33 | contact@furthington.com jeaye 34 | support@furthington.com jeaye 35 | 36 | spam@pastespace.org jeaye 37 | junk@pastespace.org jeaye 38 | junk@jeaye.com jeaye 39 | 40 | contact@fu-er.com fu-er 41 | contact@penelope-art.com fu-er 42 | contact@penny-art.com fu-er 43 | kitty@pastespace.org fu-er 44 | ''; 45 | postmasterAlias = "root"; 46 | rootAlias = "jeaye"; 47 | 48 | extraAliases = 49 | '' 50 | # Basic system aliases -- these MUST be present 51 | MAILER-DAEMON: postmaster 52 | 53 | # General redirections for pseudo accounts 54 | bin: root 55 | daemon: root 56 | named: root 57 | nobody: root 58 | uucp: root 59 | www: root 60 | ftp-bugs: root 61 | postfix: root 62 | 63 | # Well-known aliases 64 | manager: root 65 | dumper: root 66 | operator: root 67 | abuse: postmaster 68 | 69 | # Trap decode to catch security attacks 70 | decode: root 71 | 72 | # Local users 73 | safepaste: jeaye 74 | ''; 75 | extraConfig = 76 | '' 77 | home_mailbox = Maildir/ 78 | virtual_alias_domains = jeaye.com safepaste.org trustcoin.org furthington.com fu-er.com penelope-art.com penny-art.com 79 | 80 | # Max email size ~20MB 81 | message_size_limit = 20480000 82 | 83 | # Prevent others from checking for valid emails 84 | disable_vrfy_command = yes 85 | 86 | # Deliver through procmail 87 | mailbox_command = ${pkgs.procmail}/bin/procmail -t -a "$EXTENSION" 88 | 89 | # Security 90 | smtpd_use_tls = yes 91 | smtpd_tls_cert_file = /var/lib/acme/pastespace.org/cert.pem 92 | smtpd_tls_key_file = /var/lib/acme/pastespace.org/key.pem 93 | smtpd_tls_session_cache_database = btree:''${queue_directory}/smtpd_scache 94 | smtpd_tls_wrappermode = no 95 | smtpd_tls_security_level = may 96 | smtpd_tls_eecdh_grade = ultra 97 | smtpd_tls_protocols = !SSLv2, !SSLv3 98 | smtpd_tls_auth_only = yes 99 | smtpd_tls_loglevel = 1 100 | 101 | smtpd_sasl_auth_enable = yes 102 | smtpd_sasl_type = dovecot 103 | smtpd_sasl_path = private/auth 104 | smtpd_sasl_authenticated_header = yes 105 | 106 | smtp_tls_security_level = may 107 | smtp_tls_eecdh_grade = ultra 108 | smtp_tls_cert_file = /var/lib/acme/pastespace.org/cert.pem 109 | smtp_tls_key_file = /var/lib/acme/pastespace.org/key.pem 110 | smtp_tls_session_cache_database = btree:''${queue_directory}/smtp_scache 111 | smtp_tls_loglevel = 1 112 | 113 | tls_random_source = dev:/dev/urandom 114 | tls_eecdh_strong_curve = prime256v1 115 | tls_eecdh_ultra_curve = secp384r1 116 | 117 | smtpd_relay_restrictions = 118 | permit_sasl_authenticated 119 | permit_mynetworks 120 | reject_unauth_destination 121 | 122 | smtpd_recipient_restrictions = 123 | permit_sasl_authenticated 124 | permit_mynetworks 125 | reject_unauth_destination 126 | reject_invalid_hostname 127 | reject_non_fqdn_hostname 128 | reject_non_fqdn_sender 129 | reject_non_fqdn_recipient 130 | reject_unknown_reverse_client_hostname 131 | 132 | smtpd_helo_restrictions = 133 | permit_sasl_authenticated 134 | permit_mynetworks 135 | reject_unknown_helo_hostname 136 | reject_invalid_hostname 137 | reject_unauth_pipelining 138 | reject_non_fqdn_hostname 139 | 140 | smtpd_helo_required = yes 141 | 142 | smtpd_data_restrictions = 143 | reject_unauth_pipelining 144 | 145 | smtpd_sender_restrictions = 146 | permit_sasl_authenticated 147 | permit_mynetworks 148 | reject_unknown_sender_domain 149 | reject_sender_login_mismatch 150 | reject_unauth_pipelining 151 | reject_non_fqdn_sender 152 | permit 153 | 154 | # OpenDKIM mail verification 155 | milter_default_action = accept 156 | milter_protocol = 2 157 | smtpd_milters = unix:/var/run/opendkim/opendkim.sock 158 | non_smtpd_milters = unix:/var/run/opendkim/opendkim.sock 159 | ''; 160 | extraMasterConf = 161 | '' 162 | submission inet n - n - - smtpd 163 | -o syslog_name=postfix/submission 164 | -o milter_macro_daemon_name=ORIGINATING 165 | -o smtpd_tls_security_level=encrypt 166 | -o smtpd_sasl_security_options=noanonymous 167 | ''; 168 | }; 169 | 170 | networking.firewall = 171 | { 172 | allowedTCPPorts = 173 | [ 174 | 25 # smtp 175 | 587 # smtp 176 | ]; 177 | }; 178 | } 179 | -------------------------------------------------------------------------------- /server/service/radicale.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | services.radicale = { 5 | enable = true; 6 | config = 7 | '' 8 | [server] 9 | hosts = 0.0.0.0:5232 10 | #base_prefix = /calendar/ 11 | #can_skip_base_prefix = True 12 | 13 | [auth] 14 | type = None 15 | 16 | [rights] 17 | type = none 18 | 19 | #[git] 20 | #committer = Radicale 21 | 22 | [logging] 23 | debug = False 24 | ''; 25 | }; 26 | 27 | environment.etc = 28 | { 29 | "radicale/logging".text = 30 | '' 31 | [loggers] 32 | keys = root 33 | 34 | [handlers] 35 | keys = console,file 36 | 37 | [formatters] 38 | keys = full 39 | 40 | [logger_root] 41 | level = WARNING 42 | handlers = console,file 43 | 44 | [handler_console] 45 | class = StreamHandler 46 | args = (sys.stdout,) 47 | formatter = full 48 | 49 | [handler_file] 50 | # File handler 51 | class = FileHandler 52 | args = ('/tmp/radicale',) 53 | formatter = full 54 | 55 | [formatter_full] 56 | format = %(asctime)s - %(levelname)s: %(message)s 57 | ''; 58 | }; 59 | } 60 | -------------------------------------------------------------------------------- /server/service/rainloop.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, lib, ... }: 2 | 3 | { 4 | environment.etc = 5 | { 6 | "upgrade-rainloop" = 7 | { 8 | text = 9 | '' 10 | export PATH=${pkgs.curl}/bin:${pkgs.wget}/bin:${pkgs.gnupg}/bin:${pkgs.rsync}/bin:${pkgs.unzip}/bin:$PATH 11 | ${lib.readFile ./data/upgrade-rainloop} 12 | ''; 13 | mode = "0774"; 14 | }; 15 | }; 16 | 17 | services.cron.systemCronJobs = 18 | [ 19 | "@daily root /etc/upgrade-rainloop" 20 | ]; 21 | } 22 | -------------------------------------------------------------------------------- /server/service/safepaste.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | environment.systemPackages = 5 | [ 6 | pkgs.boot 7 | pkgs.nodejs 8 | pkgs.openjdk 9 | ]; 10 | 11 | nixpkgs.config = 12 | { 13 | packageOverrides = pkgs: rec 14 | { 15 | safepaste = pkgs.callPackage ../pkg/safepaste.nix { }; 16 | }; 17 | }; 18 | 19 | environment.etc."user/safepaste/run-server" = 20 | { 21 | text = 22 | '' 23 | #!/run/current-system/sw/bin/bash 24 | set -eu 25 | export PATH=${pkgs.openssl}/bin:$PATH 26 | 27 | cd /etc/user/safepaste 28 | #for p in about donate; 29 | #do 30 | # ${pkgs.safepaste}/bin/encrypt $p ${pkgs.safepaste}/share /etc/user/safepaste/paste 31 | #done 32 | ${pkgs.openjdk}/bin/java -jar ${pkgs.safepaste}/bin/safepaste-standalone.jar 33 | ''; 34 | mode = "0775"; 35 | }; 36 | 37 | systemd.services.safepaste = 38 | { 39 | wantedBy = [ "multi-user.target" ]; 40 | after = [ "network.target" ]; 41 | serviceConfig = 42 | { 43 | User = "safepaste"; 44 | WorkingDirectory = "/etc/user/safepaste"; 45 | ExecStart = "/etc/user/safepaste/run-server"; 46 | }; 47 | }; 48 | 49 | services.cron = 50 | { 51 | systemCronJobs = 52 | [ 53 | "0 */1 * * * safepaste ${pkgs.safepaste}/bin/clean-expired /etc/user/safepaste/paste" 54 | ]; 55 | }; 56 | 57 | 58 | users.users.safepaste = 59 | { 60 | isNormalUser = false; 61 | home = "/etc/user/safepaste"; 62 | createHome = true; 63 | }; 64 | environment.etc."user/safepaste/paste/.manage-directory".text = ""; 65 | 66 | system.activationScripts = 67 | { 68 | safepaste-home = 69 | { 70 | deps = []; 71 | text = 72 | '' 73 | chown -R safepaste:users /etc/user/safepaste 74 | ''; 75 | }; 76 | }; 77 | 78 | networking.firewall.allowedTCPPorts = [ 3000 ]; 79 | 80 | services.fail2ban = 81 | { 82 | jails.safepaste = 83 | '' 84 | filter = safepaste 85 | maxretry = 10 86 | findtime = 43200 87 | action = safepaste 88 | bantime = 43200 89 | enabled = true 90 | ''; 91 | }; 92 | 93 | environment.etc."fail2ban/filter.d/safepaste.conf".text = 94 | '' 95 | [Definition] 96 | failregex = Paste from .* 97 | ''; 98 | environment.etc."fail2ban/action.d/safepaste.conf".text = 99 | '' 100 | [Definition] 101 | actionstart = touch /var/tmp/safepaste.ban 102 | chmod a+r /var/tmp/safepaste.ban 103 | actionstop = sed -i '/.*/d' /var/tmp/safepaste.ban 104 | actioncheck = 105 | actionban = ${pkgs.safepaste}/bin/ban add /var/tmp 106 | actionunban = ${pkgs.safepaste}/bin/ban remove /var/tmp 107 | ''; 108 | } 109 | -------------------------------------------------------------------------------- /server/service/spamassassin.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | services.spamassassin = 5 | { 6 | enable = true; 7 | config = 8 | '' 9 | use_bayes 1 10 | bayes_auto_learn 0 11 | ''; 12 | }; 13 | 14 | # Regularly update spamassassin rules and train 15 | services.cron.systemCronJobs = 16 | [ 17 | "@daily root ${pkgs.spamassassin}/bin/sa-update && systemctl restart spamd" 18 | "@daily root /etc/train-spamassassin" 19 | ]; 20 | 21 | # https://github.com/NixOS/nixpkgs/issues/7915#issuecomment-104882091 22 | environment.etc = 23 | { 24 | "procmailrc" = 25 | { 26 | text = 27 | '' 28 | SHELL="/bin/bash" 29 | LINEBUF=4096 30 | SENDMAIL="/run/wrappers/bin/sendmail -oi -t" 31 | DEFAULT="$HOME/Maildir/" 32 | MAILDIR="$HOME/Maildir/" 33 | DROPPRIVS="yes" 34 | VERBOSE=on 35 | LOGFILE=$HOME/.procmail.log 36 | 37 | :0fw 38 | * < 512000 39 | | ${pkgs.spamassassin}/bin/spamc 40 | 41 | :0: 42 | * ^X-Spam-Status: Yes 43 | .Spam/ 44 | 45 | # Work around procmail bug: any output on stderr will cause the 46 | # "F" in "From" to be dropped. This will re-add it. 47 | :0 48 | * ^^rom[ ] 49 | { 50 | LOG="*** Dropped F off From_ header! Fixing up. " 51 | 52 | :0 fhw 53 | | sed -e '1s/^/F/' 54 | } 55 | 56 | # Apply user rules 57 | INCLUDERC=$HOME/.procmailrc 58 | ''; 59 | }; 60 | "train-spamassassin" = 61 | { 62 | text = 63 | '' 64 | #!/run/current-system/sw/bin/bash 65 | set -eu 66 | 67 | # TODO: Possibly run for other users 68 | ${pkgs.spamassassin}/bin/sa-learn --no-sync --spam /etc/user/jeaye/Maildir/.Spam/{cur,new} 69 | ${pkgs.spamassassin}/bin/sa-learn --no-sync --ham /etc/user/jeaye/Maildir/.Ham/{cur,new} 70 | ${pkgs.spamassassin}/bin/sa-learn --no-sync --ham /etc/user/jeaye/Maildir/.ML*/{cur,new} 71 | ${pkgs.spamassassin}/bin/sa-learn --sync 72 | ''; 73 | mode = "0774"; 74 | }; 75 | }; 76 | } 77 | -------------------------------------------------------------------------------- /server/service/taskserver.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | services.taskserver = 5 | { 6 | enable = true; 7 | fqdn = "pastespace.org"; 8 | listenHost = "::"; 9 | organisations.default.users = [ "jeaye" ]; 10 | }; 11 | 12 | networking.firewall = 13 | { 14 | allowedTCPPorts = [ 53589 ]; 15 | }; 16 | } 17 | -------------------------------------------------------------------------------- /server/service/upload.jeaye.com-tmp.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | # Uploading files via SSH is done through this user and a cron job. Better 5 | # to not expose the whole http user to SSH. 6 | users.users.http-upload = 7 | { 8 | isNormalUser = true; 9 | home = "/etc/user/http-upload"; 10 | extraGroups = [ "ssh" ]; 11 | openssh.authorizedKeys.keys = 12 | [ 13 | "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDL8j6NtvibZpsDLWSjsPMIjUQRYHta/a8XpOJf7CQ2Aze73oFwBPaAvP1iSmpLkFCs0hp+8w0P4+eHAjp67mLgVLIvM0iESpj8YbVJACyL2Gu2J8fN63CFP3HAMEmvXGK8LSpBEErF44az0H8ZrMJPODkUYiQMX2kAgshUjtMaUqicZmWRRsiJ8bBcK2ddsWOXPzY/0j8+9KMre8YaFJve/QgmJEvVpdxt8pqklPCiMHjFI0EKRHV835mDLe/fzYK2hrTzRXw5hRpluonGce7Tg7WsVk/SmGdfysJAYOOvUwcLosK64bsg2+wIdEKG4r/Ws9FR2hqykspzx4s2o6jL jeaye@oryx" 14 | "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQD0cNcqr6VeQjQqtwhxE0IcqpQo+jULXbmKsyILFoigP5chpCVKv9qYUqk5mTjiLH9TzsC17z6CIOHGIXCxZABqpAXrPoHe8kn3WXYX04l4PWRTzeuUg2SIhTv0CwUDZGCnaTVlGpLd6CCHFbxp/4fDQ4C53NdBVu0zGeuRACutF+OTpGgsdJ8JyDBn8z9+IMgxMM1K2C5geiz2arNpQJDbu/RvZBO7bD2JDUKBRkNAv986vNdpgZvrVUR3Jhg7RVPQEioVg7jF3WmOHwMX8pYlL7Nk4tLHIfOj02Gh2FsSq8aYgTsYD4+a5A4ZSmJlP1is3N6+lu/hIcITF8A8nBBNAPIKfSY1HD5XMgjObQudtCvF15LACJgtrCV7HCIcfWklra7DcQsfcuKHGMFWDFjCer7lbUIBAeV7QbNhR/H5H3vu2kTN94myStCCmjs3KzgztP/UKWEKyes7a8+7LcUwu/zHxTw/9xTFVf5YW40gMEfuS3IFJzLf5s2yK0jd91rDEtWd+/uFqLcgjFxhd75Y/JmWYgpNRfpEva+N8A3aDrJ1t/GKUtz4AhT+D1Iu0lmJOdAvjnolbruFC3LnQxnYvlifrkRv4knjW7UA2+KEKTmHhggdJoEORsgfTDcG99Kv/PXeheY/JrGeHzJvJ7RssbxlXD8WC71FKKtmJStCyQ== pwilkerson@uber.com" 15 | "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQD0BDvQ+CHyLXY6HtJyRwwBq+9RdeKmRjt1TNshg34jAL1PQFoAxP4Bnk0IQLM9N2EuDwr6kLZt0l8JKozwSh4zPx9JU4nsFM5FjodgjNJRiMkJ+UUHJMtcQwEVKN5yEzJaXOWOcc8RYeQdJaj5s8LcYHeuv8DPQo55jlabLWvgJurISDvBDJ968kqmYA8r83ZI4xqvUH1E2PnYz7Yg1uPwMG8I8PFYKb6WWa4c+e5vJGiXJamqYPPcuFrEaT517JjMJSo/x2OcrXVTxQ4X39i+Qgi8W7CuuSypRh9/ozUdf8rVPk0/gI51D9Y48OLjrIh1bIKeMfTtgEhXl569EjzwHnsfOjq9HY2J4EdvrwoZB2kPwOrkDzRGCThYCuuxsmed+nZCztW0emmdjkos3vINsF+4foMrs3ucE6TDfsKJvQzB+TZ3pXmPzncKV36RBrucgJIMUOIg0Snc8o/YfuAHe57U5zHwTUKBILJNRMMSLlpbpRSmoJVYuDWA+goycBFGWDFy60BLGWNYpu3KrXnv/ggai3QdFAKtq7AzepOyP+0JtG/19z/dyG7xeUNlvBOVyuLlhxks9pQftyWkhl5+ATvG3ri/NQWnobw9D4x7NnGfbxI4/upWTuuh9QvS3ujGpPSOlPos0g3CTsfNq/664lrLDaWfE0FFAklgT7SpxQ== pwilkerson@uber.com" 16 | ]; 17 | }; 18 | 19 | environment.etc = 20 | { 21 | "user/http-upload/queue/.manage-directory".text = ""; 22 | "user/http-upload/flush" = 23 | { 24 | text = 25 | '' 26 | #!/run/current-system/sw/bin/bash 27 | set -eu 28 | 29 | queue=/etc/user/http-upload/queue 30 | 31 | # Check if it's empty first 32 | if [ ".manage-directory" = "$(ls -A $queue)" ]; 33 | then 34 | exit 0 35 | fi 36 | 37 | for file in $queue/*; 38 | do 39 | basename=$(basename "$file") 40 | mv -f "$file" /etc/user/http/upload.jeaye.com/tmp/ 41 | chown -R http /etc/user/http/upload.jeaye.com/tmp/"$basename" 42 | done 43 | ''; 44 | mode = "0774"; 45 | }; 46 | }; 47 | 48 | # Clean up old files and flush queue regularly. 49 | services.cron.systemCronJobs = 50 | [ 51 | "0 0 * * * http ${pkgs.findutils}/bin/find /etc/user/http/upload.jeaye.com/tmp -mtime +2 -type f -exec rm -vf {} \\;" 52 | "* * * * * root /etc/user/http-upload/flush" 53 | ]; 54 | } 55 | -------------------------------------------------------------------------------- /server/service/wordy-word.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | environment.systemPackages = 5 | [ 6 | pkgs.leiningen 7 | pkgs.openjdk 8 | ]; 9 | 10 | nixpkgs.config = 11 | { 12 | packageOverrides = pkgs: rec 13 | { 14 | wordy-word = pkgs.callPackage ../pkg/wordy-word.nix { }; 15 | }; 16 | }; 17 | 18 | environment.etc."user/wordy-word/run-server" = 19 | { 20 | text = 21 | '' 22 | #!/run/current-system/sw/bin/bash 23 | set -eu 24 | 25 | ${pkgs.openjdk}/bin/java -jar ${pkgs.wordy-word}/bin/wordy-word.jar 26 | ''; 27 | mode = "0775"; 28 | }; 29 | 30 | systemd.services.wordy-word = 31 | { 32 | wantedBy = [ "multi-user.target" ]; 33 | after = [ "network.target" ]; 34 | serviceConfig = 35 | { 36 | User = "wordy-word"; 37 | WorkingDirectory = "/etc/user/wordy-word"; 38 | ExecStart = "/etc/user/wordy-word/run-server"; 39 | }; 40 | }; 41 | 42 | users.users.wordy-word = 43 | { 44 | isNormalUser = true; 45 | home = "/etc/user/wordy-word"; 46 | createHome = true; 47 | }; 48 | 49 | system.activationScripts = 50 | { 51 | wordy-word-home = 52 | { 53 | deps = []; 54 | text = 55 | '' 56 | export PATH=${pkgs.wget}/bin:${pkgs.gnutar}/bin:${pkgs.gzip}/bin:$PATH 57 | if [ ! -f /etc/user/wordy-word/unapproved-nouns ]; 58 | then 59 | pushd /etc/user/wordy-word 60 | ${pkgs.wordy-word}/bin/build-word-lists 61 | popd 62 | fi 63 | chown -R wordy-word:users /etc/user/wordy-word 64 | ''; 65 | }; 66 | }; 67 | } 68 | -------------------------------------------------------------------------------- /server/system/environment.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | # This is a headless machine; no need for anything fancy... or so I thought. 5 | # Enabling noXlibs requires manual compilation of some large packages, like 6 | # openjdk. I'll try to disable it, to avoid massive compilations, with the 7 | # tradeoff of a larger /nix/store and attack vector. 8 | environment.noXlibs = false; 9 | fonts.fontconfig.enable = false; 10 | sound.enable = false; 11 | 12 | # Auto GC every morning 13 | nix.gc.automatic = false; 14 | services.cron.systemCronJobs = [ "0 3 * * * root /etc/admin/optimize-nix" ]; 15 | 16 | environment.etc = 17 | { 18 | "admin/optimize-nix" = 19 | { 20 | text = 21 | '' 22 | #!/run/current-system/sw/bin/bash 23 | set -eu 24 | 25 | # Delete everything from this profile that isn't currently needed 26 | nix-env --delete-generations old 27 | 28 | # Delete generations older than a week 29 | nix-collect-garbage 30 | nix-collect-garbage --delete-older-than 7d 31 | 32 | # Optimize 33 | nix-store --gc --print-dead 34 | nix-store --optimise 35 | ''; 36 | mode = "0774"; 37 | }; 38 | }; 39 | } 40 | -------------------------------------------------------------------------------- /server/system/network.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | networking = 5 | { 6 | wireless.enable = false; 7 | enableIPv6 = false; 8 | 9 | # Allow containers to have private networks 10 | nat = 11 | { 12 | enable = true; 13 | internalInterfaces = ["ve-+"]; 14 | externalInterface = "ens3"; 15 | }; 16 | }; 17 | } 18 | -------------------------------------------------------------------------------- /server/system/security.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | security.sudo = 5 | { 6 | enable = false; 7 | wheelNeedsPassword = true; 8 | }; 9 | } 10 | -------------------------------------------------------------------------------- /server/system/user.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | system.activationScripts = 5 | { 6 | homes = 7 | { 8 | deps = []; 9 | text = (builtins.foldl' 10 | (us: u: 11 | '' 12 | ${us} 13 | ln -sf /etc/user/dotfiles/bash_profile /etc/user/${u.name}/.bash_profile 14 | ln -sf /etc/user/dotfiles/bashrc /etc/user/${u.name}/.bashrc 15 | ln -sf /etc/user/dotfiles/dir_colors /etc/user/${u.name}/.dir_colors 16 | ln -sf /etc/user/dotfiles/gitconfig /etc/user/${u.name}/.gitconfig 17 | ln -sf /etc/user/dotfiles/gitignore /etc/user/${u.name}/.gitignore 18 | ln -sf /etc/user/dotfiles/tmux.conf /etc/user/${u.name}/.tmux.conf 19 | ln -sf /etc/user/dotfiles/elinks /etc/user/${u.name}/.elinks 20 | chown -R ${u.name}:users /etc/user/${u.name} 21 | '') 22 | "" 23 | (builtins.filter (u: u.isNormalUser) 24 | (map (key: builtins.getAttr key config.users.users) 25 | (builtins.attrNames config.users.users)))); 26 | }; 27 | root-home = 28 | { 29 | deps = []; 30 | text = 31 | '' 32 | ln -sf /etc/user/dotfiles/bash_profile /root/.bash_profile 33 | ln -sf /etc/user/dotfiles/bashrc /root/.bashrc 34 | ln -sf /etc/user/dotfiles/dir_colors /root/.dir_colors 35 | ln -sf /etc/user/dotfiles/tmux.conf /root/.tmux.conf 36 | ln -sf /etc/user/dotfiles/tmux-nixos.conf /root/.tmux-nixos.conf 37 | ''; 38 | }; 39 | }; 40 | 41 | # Allow useradd/groupadd imperatively 42 | users.mutableUsers = true; 43 | } 44 | -------------------------------------------------------------------------------- /server/user/fu-er.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | users.users.fu-er = 5 | { 6 | isNormalUser = true; 7 | home = "/etc/user/fu-er"; 8 | extraGroups = [ "ssh" ]; 9 | }; 10 | 11 | environment.etc = 12 | { 13 | "user/fu-er/.procmailrc" = 14 | { 15 | text = 16 | '' 17 | INCLUDERC=/etc/user/fu-er/.procmail/spam.rc 18 | ''; 19 | }; 20 | "user/fu-er/.procmail/spam.rc" = 21 | { 22 | text = 23 | '' 24 | # TrueIdentity 25 | :0: 26 | * ^From: .*e-tui\.transunion\.com.* 27 | .Trash/ 28 | 29 | # Junk 30 | :0: 31 | * ^(From|Cc|To|X-Original-To): kitty@pastespace\.org 32 | .Junk/ 33 | ''; 34 | }; 35 | }; 36 | } 37 | -------------------------------------------------------------------------------- /server/user/git.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | users.users.git = 5 | { 6 | isNormalUser = true; 7 | home = "/etc/user/git"; 8 | createHome = true; 9 | extraGroups = [ "ssh" ]; 10 | }; 11 | users.groups.git = {}; 12 | 13 | # Ensure some directories exist 14 | environment.etc."user/git/dotfiles/.manage-directory".text = ""; 15 | 16 | # XXX: Manually bring in dotfiles repo 17 | system.activationScripts = 18 | { 19 | git-home = 20 | { 21 | deps = []; 22 | text = 23 | '' 24 | PATH=${pkgs.git}/bin:$PATH 25 | PATH=${pkgs.gnused}/bin:$PATH 26 | 27 | if [ ! -d /etc/user/dotfiles ]; 28 | then 29 | git clone --recursive /etc/user/git/dotfiles /etc/user/dotfiles 30 | fi 31 | chgrp -R git /etc/user/dotfiles 32 | chmod -R g+w /etc/user/dotfiles 33 | ''; 34 | }; 35 | }; 36 | } 37 | -------------------------------------------------------------------------------- /server/user/irc.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | environment.systemPackages = with pkgs; 5 | [ 6 | weechat 7 | aspell 8 | aspellDicts.en 9 | ]; 10 | 11 | users.users.irc = 12 | { 13 | isNormalUser = true; 14 | home = "/etc/user/irc"; 15 | createHome = true; 16 | extraGroups = [ "git" ]; 17 | }; 18 | 19 | system.activationScripts = 20 | { 21 | irc-home = 22 | { 23 | deps = []; 24 | text = 25 | '' 26 | ln -sf /etc/user/dotfiles/weechat /etc/user/irc/.weechat 27 | ''; 28 | }; 29 | }; 30 | 31 | networking.firewall = 32 | { 33 | allowedTCPPorts = 34 | [ 35 | 113 # ident 36 | ]; 37 | }; 38 | } 39 | -------------------------------------------------------------------------------- /server/user/jeaye.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | let 4 | spamassassin_prefs = 5 | '' 6 | required_score 3 7 | report_safe 0 8 | score BAYES_00 -4 9 | score BAYES_05 -2 10 | score BAYES_95 6 11 | score BAYES_99 9 12 | ''; 13 | in 14 | { 15 | environment.systemPackages = with pkgs; 16 | [ 17 | tmux 18 | neomutt 19 | pinentry 20 | gnupg 21 | ]; 22 | 23 | users.users.jeaye = 24 | { 25 | isNormalUser = true; 26 | home = "/etc/user/jeaye"; 27 | extraGroups = [ "wheel" "ssh" ]; 28 | }; 29 | 30 | system.activationScripts = 31 | { 32 | jeaye-home = 33 | { 34 | deps = []; 35 | text = 36 | '' 37 | PATH=${pkgs.git}/bin:$PATH 38 | PATH=${pkgs.gnused}/bin:$PATH 39 | 40 | if [ ! -d /etc/user/jeaye/.vim ]; 41 | then 42 | # TODO: Network IO in an activation script is bad 43 | git clone --recursive https://github.com/jeaye/vimrc.git /etc/user/jeaye/.vim 44 | ln -sf /etc/user/jeaye/.vim/vimrc /etc/user/jeaye/.vimrc 45 | fi 46 | chown -R jeaye:users /etc/user/jeaye/.vim 47 | 48 | user_prefs=/var/lib/spamassassin/user-jeaye/user_prefs 49 | rm -f "$user_prefs" 50 | echo "${spamassassin_prefs}" > "$user_prefs" 51 | chown spamd:spamd "$user_prefs" 52 | chmod 0600 "$user_prefs" 53 | ''; 54 | }; 55 | }; 56 | 57 | environment.etc = 58 | { 59 | "user/jeaye/.procmailrc" = 60 | { 61 | text = 62 | '' 63 | INCLUDERC=/etc/user/jeaye/.procmail/list.rc 64 | INCLUDERC=/etc/user/jeaye/.procmail/work.rc 65 | INCLUDERC=/etc/user/jeaye/.procmail/admin.rc 66 | ''; 67 | }; 68 | "user/jeaye/.procmail/list.rc" = 69 | { 70 | text = 71 | '' 72 | # Clojure mailing list 73 | :0: 74 | * ^X-BeenThere: clojure@googlegroups\.com 75 | .ML.Clojure/ 76 | 77 | # ClojureScript mailing list 78 | :0: 79 | * ^X-BeenThere: clojurescript@googlegroups\.com 80 | .ML.ClojureScript/ 81 | 82 | # Clang mailing list 83 | :0: 84 | * ^X-BeenThere: cfe-(users|dev)@cs\.uiuc\.edu 85 | .ML.Clang/ 86 | 87 | # ISOC++ mailing list 88 | :0: 89 | * ^X-BeenThere: std-(proposals|discussion)@isocpp\.org 90 | .ML.ISOCPP/ 91 | 92 | # Slackware mailing list 93 | :0: 94 | * ^(From|Cc|To).*slackware-(security|announce)@slackware\.com 95 | .ML.Slackware/ 96 | 97 | # NixOS mailing list 98 | :0: 99 | * ^X-BeenThere: nix-dev@lists\.science\.uu\.nl 100 | .ML.NixOS/ 101 | 102 | # NixOS-Security mailing list 103 | :0: 104 | * ^X-BeenThere: nix-security-announce@googlegroups\.com 105 | .ML.NixOS-Sec/ 106 | 107 | # Junk 108 | :0: 109 | * ^(From|Cc|To): (junk@pastespace\.org|junk@jeaye.com)|lorgonjortle.* 110 | .Junk/ 111 | ''; 112 | }; 113 | "user/jeaye/.procmail/work.rc" = 114 | { 115 | text = 116 | '' 117 | # Furthington bucket 118 | :0: 119 | * ^(From|Cc|To).*furthington\.com 120 | .Furthington/ 121 | 122 | # Hiring bucket 123 | :0: 124 | * ^(From|Cc|To).*(hiring@okletsplay.com) 125 | .LetsBet-Hiring/ 126 | 127 | # LetsBet bucket 128 | :0: 129 | * ^(From|Cc|To).*(russalek13.*|.*@okletsplay.com) 130 | .LetsBet/ 131 | 132 | # TinyCo bucket 133 | :0: 134 | * ^(From|Cc|To).*brooklynpacket/.* 135 | .TinyCo/ 136 | ''; 137 | }; 138 | "user/jeaye/.procmail/admin.rc" = 139 | { 140 | text = 141 | '' 142 | # DMARC reports 143 | :0: 144 | * ^Subject: Report [dD]omain: 145 | .ML.DMARC/ 146 | 147 | # Cron reports 148 | :0: 149 | * ^From: Cron Daemon 150 | .Cron/ 151 | ''; 152 | }; 153 | }; 154 | } 155 | -------------------------------------------------------------------------------- /server/user/okletsplay.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | users.users.okletsplay = 5 | { 6 | isNormalUser = false; 7 | createHome = false; 8 | }; 9 | } 10 | -------------------------------------------------------------------------------- /server/util/acme.nix: -------------------------------------------------------------------------------- 1 | {}: 2 | 3 | { 4 | util.acme = 5 | { 6 | directory = "/var/lib/acme-unstable"; 7 | plugins = [ "account_reg.json" "account_key.json" "fullchain.pem" "chain.pem" "key.pem" "cert.pem" ]; 8 | post-run = 9 | '' 10 | cp -R /var/lib/acme-unstable/* /var/lib/acme/ 11 | systemctl restart httpd.service ; 12 | ''; 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /server/util/http.nix: -------------------------------------------------------------------------------- 1 | {}: 2 | 3 | { 4 | util.http = 5 | { 6 | # Basic config 7 | defaults = 8 | { 9 | user = "http"; 10 | adminAddr = "contact@jeaye.com"; 11 | logPerVirtualHost = true; 12 | multiProcessingModule = "event"; 13 | 14 | extraConfig = 15 | '' 16 | AddDefaultCharset UTF-8 17 | AddCharset UTF-8 .html .htm .txt 18 | 19 | ServerTokens Prod 20 | ServerSignature Off 21 | TraceEnable off 22 | 23 | # Prefer HTTP2 24 | Protocols h2 h2c http/1.1 25 | ''; 26 | }; 27 | 28 | helpers = 29 | rec { 30 | sslInfo = domain: cert_domain: 31 | '' 32 | 33 | AllowOverride None 34 | Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec 35 | Require method GET POST OPTIONS 36 | 37 | Alias /.well-known/ /etc/user/http/${domain}/.well-known/ 38 | 39 | SSLCertificateKeyFile /var/lib/acme/${cert_domain}/key.pem 40 | SSLCertificateChainFile /var/lib/acme/${cert_domain}/chain.pem 41 | SSLCertificateFile /var/lib/acme/${cert_domain}/cert.pem 42 | SSLProtocol All -SSLv2 -SSLv3 43 | SSLCipherSuite HIGH:!aNULL:!MD5:!EXP 44 | SSLHonorCipherOrder on 45 | ''; 46 | ignoreDirectory = domain: 47 | '' 48 | 49 | Options -Indexes 50 | 51 | ''; 52 | withSSL = domain: cert_domain: (ignoreDirectory domain) 53 | + (sslInfo domain cert_domain); 54 | }; 55 | }; 56 | } 57 | -------------------------------------------------------------------------------- /shared/configuration.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | imports = 5 | [ 6 | ## System 7 | ./system/environment.nix 8 | ./system/network.nix 9 | ./system/systemd.nix 10 | ./system/security.nix 11 | 12 | ## Users 13 | ./system/user.nix 14 | 15 | ## Services 16 | ./service/time.nix 17 | ./service/locate.nix 18 | ./service/ssh.nix 19 | ]; 20 | } 21 | -------------------------------------------------------------------------------- /shared/service/locate.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | services.locate.enable = true; 5 | } 6 | -------------------------------------------------------------------------------- /shared/service/ssh.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, lib, ... }: 2 | 3 | { 4 | services.openssh = 5 | { 6 | enable = true; 7 | allowSFTP = lib.mkDefault false; 8 | settings = 9 | { 10 | X11Forwarding = false; 11 | PermitRootLogin = "no"; 12 | }; 13 | hostKeys = 14 | [ 15 | { type = "ed25519"; path = "/etc/ssh/ssh_host_ed25519_key"; } 16 | { type = "rsa"; bits = 4096; path = "/etc/ssh/ssh_host_rsa_key"; } 17 | ]; 18 | extraConfig = 19 | '' 20 | PermitEmptyPasswords no 21 | 22 | # Avoid DNS lookups. 23 | UseDNS no 24 | 25 | # Throttle to a reasonable amount for a small server. 26 | MaxStartups 5 27 | MaxSessions 5 28 | MaxAuthTries 5 29 | 30 | # Don't allow just anyone to use SSH. 31 | AllowGroups ssh 32 | 33 | # LogLevel VERBOSE logs user's key fingerprint on login. 34 | # Needed to have a clear audit track of which key was used to log in. 35 | LogLevel VERBOSE 36 | 37 | # Use kernel sandbox mechanisms where possible in unprivileged processes. 38 | UsePrivilegeSeparation sandbox 39 | ''; 40 | }; 41 | 42 | networking.firewall.allowedTCPPorts = lib.mkDefault [ 22 ]; 43 | } 44 | -------------------------------------------------------------------------------- /shared/service/time.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | time.timeZone = "America/Los_Angeles"; 5 | services.ntp.enable = false; 6 | } 7 | -------------------------------------------------------------------------------- /shared/system/boot.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | boot.kernelParams = [ "boot.shell_on_fail" ]; 5 | 6 | boot.loader.systemd-boot.enable = true; 7 | boot.loader.efi.canTouchEfiVariables = true; 8 | 9 | # Clean up /tmp on boot 10 | boot.cleanTmpDir = true; 11 | 12 | swapDevices = 13 | [ 14 | { 15 | # Nix will create this automagically 16 | device = "/swap"; 17 | size = 2048; 18 | } 19 | ]; 20 | } 21 | -------------------------------------------------------------------------------- /shared/system/environment.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | i18n = 5 | { 6 | defaultLocale = "en_US.UTF-8"; 7 | }; 8 | console = 9 | { 10 | keyMap = "us"; 11 | font = "Lat2-Terminus16"; 12 | }; 13 | 14 | i18n.extraLocaleSettings = { 15 | LC_ADDRESS = "en_US.UTF-8"; 16 | LC_IDENTIFICATION = "en_US.UTF-8"; 17 | LC_MEASUREMENT = "en_US.UTF-8"; 18 | LC_MONETARY = "en_US.UTF-8"; 19 | LC_NAME = "en_US.UTF-8"; 20 | LC_NUMERIC = "en_US.UTF-8"; 21 | LC_PAPER = "en_US.UTF-8"; 22 | LC_TELEPHONE = "en_US.UTF-8"; 23 | LC_TIME = "en_US.UTF-8"; 24 | }; 25 | 26 | programs.bash.enableCompletion = true; 27 | 28 | nix.settings.allowed-users = [ "@wheel" ]; 29 | nix.optimise = 30 | { 31 | automatic = true; 32 | dates = [ "weekly" ]; 33 | }; 34 | nix.gc = 35 | { 36 | automatic = true; 37 | dates = "weekly"; 38 | options = "--delete-older-than 7d"; 39 | }; 40 | } 41 | -------------------------------------------------------------------------------- /shared/system/network.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | networking = 5 | { 6 | firewall = 7 | { 8 | enable = true; 9 | allowPing = true; 10 | }; 11 | }; 12 | } 13 | -------------------------------------------------------------------------------- /shared/system/security.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | } 5 | -------------------------------------------------------------------------------- /shared/system/systemd.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | services.journald.extraConfig = 5 | '' 6 | Storage=persist 7 | Compress=yes 8 | SystemMaxUse=128M 9 | RuntimeMaxUse=8M 10 | ''; 11 | } 12 | -------------------------------------------------------------------------------- /shared/system/user.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | # TODO: Good values here. 5 | # security.pam.loginLimits = 6 | # [ 7 | # { domain = "*"; item = "nproc"; type = "soft"; value = "1024"; } 8 | # { domain = "*"; item = "nproc"; type = "hard"; value = "1024"; } 9 | # { domain = "*"; item = "maxlogins"; type = "hard"; value = "3"; } 10 | # { domain = "*"; item = "nofile"; type = "hard"; value = "1024"; } 11 | # ]; 12 | 13 | # Required for SSH access. 14 | users.groups.ssh = {}; 15 | } 16 | -------------------------------------------------------------------------------- /workstation/configuration.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | # TODO: 4 | # firejail 5 | 6 | { 7 | hardware.system76.enableAll = true; 8 | 9 | imports = 10 | [ 11 | ./hardware-configuration.nix # Auto-generated by nixos 12 | ../shared/configuration.nix 13 | 14 | ## More secure defaults 15 | # TODO: Can we have this? 16 | # 17 | 18 | ## System 19 | ./system/boot.nix 20 | ./system/environment.nix 21 | ./system/network.nix 22 | ./system/security.nix 23 | ./system/sound.nix 24 | ./system/usb.nix 25 | 26 | ## Global programs 27 | ./program/essential.nix 28 | 29 | ## Users 30 | ./system/user.nix 31 | ./user/jeaye.nix 32 | 33 | ## Services 34 | ./service/x11.nix 35 | ./service/virtualbox.nix 36 | 37 | # Overrides. 38 | ./service/ssh.nix 39 | ./service/docker.nix 40 | ]; 41 | 42 | system.stateVersion = "23.11"; 43 | } 44 | -------------------------------------------------------------------------------- /workstation/hardware-configuration.nix: -------------------------------------------------------------------------------- 1 | # Do not modify this file! It was generated by ‘nixos-generate-config’ 2 | # and may be overwritten by future invocations. Please make changes 3 | # to /etc/nixos/configuration.nix instead. 4 | { config, lib, pkgs, modulesPath, ... }: 5 | 6 | { 7 | imports = 8 | [ (modulesPath + "/installer/scan/not-detected.nix") 9 | ]; 10 | 11 | boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "nvme" "usbhid" "usb_storage" "sd_mod" ]; 12 | boot.initrd.kernelModules = [ ]; 13 | boot.kernelModules = [ "kvm-amd" ]; 14 | boot.extraModulePackages = [ ]; 15 | 16 | fileSystems."/" = 17 | { device = "/dev/disk/by-uuid/f8075176-413f-467c-8686-8b54bde595eb"; 18 | fsType = "ext4"; 19 | }; 20 | 21 | boot.initrd.luks.devices."luks-a7845599-2a15-4155-ab69-a023bf7a2034".device = "/dev/disk/by-uuid/a7845599-2a15-4155-ab69-a023bf7a2034"; 22 | 23 | fileSystems."/boot" = 24 | { device = "/dev/disk/by-uuid/9345-1BA8"; 25 | fsType = "vfat"; 26 | }; 27 | 28 | swapDevices = [ ]; 29 | 30 | # Enables DHCP on each ethernet and wireless interface. In case of scripted networking 31 | # (the default) this is the recommended approach. When using systemd-networkd it's 32 | # still possible to use this option, but it's recommended to use it in conjunction 33 | # with explicit per-interface declarations with `networking.interfaces..useDHCP`. 34 | networking.useDHCP = lib.mkDefault true; 35 | # networking.interfaces.enp4s0.useDHCP = lib.mkDefault true; 36 | # networking.interfaces.enp6s0.useDHCP = lib.mkDefault true; 37 | # networking.interfaces.wlo2.useDHCP = lib.mkDefault true; 38 | 39 | nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; 40 | hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; 41 | } 42 | -------------------------------------------------------------------------------- /workstation/program/essential.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | environment.systemPackages = let pkgsUnstable = import 5 | ( 6 | fetchTarball https://github.com/NixOS/nixpkgs/archive/master.tar.gz 7 | ) 8 | { }; 9 | in 10 | with pkgs; 11 | [ 12 | ## Vim 13 | neovim 14 | tree-sitter 15 | fzf 16 | silver-searcher 17 | ripgrep 18 | 19 | ## Browsing/downloading 20 | wget 21 | 22 | ## Reading 23 | #pkgsUnstable.koodo-reader 24 | 25 | ## File formats 26 | unzip 27 | file 28 | 29 | ## Networking 30 | traceroute 31 | sshfs 32 | 33 | ## Source control 34 | git 35 | git-lfs 36 | 37 | ## Shell 38 | tmux 39 | # 0.13.0 migrated to toml 40 | pkgsUnstable.alacritty 41 | starship 42 | pcre 43 | 44 | ## Administration 45 | htop 46 | psmisc 47 | lm_sensors 48 | 49 | # Hardware 50 | uhk-agent 51 | 52 | # Nix 53 | nix-index 54 | ]; 55 | 56 | hardware.keyboard.uhk.enable = true; 57 | } 58 | -------------------------------------------------------------------------------- /workstation/service/docker.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | virtualisation.docker = 5 | { 6 | enable = true; 7 | enableNvidia = false; 8 | }; 9 | } 10 | -------------------------------------------------------------------------------- /workstation/service/ssh.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | services.openssh.allowSFTP = true; 5 | networking.firewall.allowedTCPPorts = [ 2234 ]; 6 | } 7 | -------------------------------------------------------------------------------- /workstation/service/virtualbox.nix: -------------------------------------------------------------------------------- 1 | { 2 | virtualisation.virtualbox.host.enable = true; 3 | users.extraGroups.vboxusers.members = [ "jeaye" ]; 4 | } 5 | -------------------------------------------------------------------------------- /workstation/service/x11.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | services.xserver = 5 | { 6 | enable = true; 7 | autorun = true; 8 | xkb.layout = "us"; 9 | #tty = 2; 10 | 11 | windowManager = 12 | { 13 | i3 = 14 | { 15 | enable = true; 16 | extraPackages = with pkgs; [ dmenu polybar i3lock hsetroot xautolock xorg.xwininfo ]; 17 | }; 18 | }; 19 | desktopManager = 20 | { 21 | xterm.enable = false; 22 | }; 23 | displayManager = 24 | { 25 | startx.enable = true; 26 | }; 27 | }; 28 | 29 | nixpkgs.overlays = [ 30 | (final: prev: { 31 | polybar = prev.polybar.override 32 | { 33 | pulseSupport = true; 34 | i3Support = true; 35 | }; 36 | }) 37 | ]; 38 | 39 | fonts = 40 | { 41 | fontconfig = 42 | { 43 | enable = true; 44 | allowBitmaps = true; 45 | useEmbeddedBitmaps = true; 46 | }; 47 | fontDir.enable = true; 48 | enableGhostscriptFonts = true; 49 | packages = with pkgs; 50 | [ 51 | google-fonts 52 | fira-code 53 | noto-fonts 54 | noto-fonts-emoji 55 | # Some international fonts. 56 | unifont 57 | # Icons. 58 | nerdfonts 59 | font-awesome 60 | material-icons 61 | material-design-icons 62 | material-symbols 63 | siji 64 | ]; 65 | }; 66 | 67 | services.redshift = 68 | { 69 | enable = true; 70 | temperature.day = 5000; 71 | temperature.night = 4500; 72 | }; 73 | location.latitude = 37.5778696; 74 | location.longitude = -122.34809; 75 | 76 | # i3 docs say this is required for i3blocks. 77 | environment.pathsToLink = [ "/libexec" ]; 78 | 79 | environment.sessionVariables = 80 | { 81 | # Allow GTK 2.0/3.0 themes to be found. 82 | GTK_DATA_PREFIX = "/run/current-system/sw"; 83 | # Allow KDE apps to work better in i3. 84 | DESKTOP_SESSION = "kde"; 85 | }; 86 | 87 | # Enable OpenGL 88 | hardware.opengl = 89 | { 90 | enable = true; 91 | #driSupport = true; 92 | driSupport32Bit = true; 93 | }; 94 | 95 | # Load nvidia driver for Xorg and Wayland 96 | services.xserver.videoDrivers = [ "nvidia" ]; 97 | 98 | hardware.nvidia = 99 | { 100 | # Modesetting is required. 101 | modesetting.enable = true; 102 | 103 | # Nvidia power management. Experimental, and can cause sleep/suspend to fail. 104 | powerManagement.enable = false; 105 | # Fine-grained power management. Turns off GPU when not in use. 106 | # Experimental and only works on modern Nvidia GPUs (Turing or newer). 107 | powerManagement.finegrained = false; 108 | 109 | # Use the NVidia open source kernel module (not to be confused with the 110 | # independent third-party "nouveau" open source driver). 111 | # Support is limited to the Turing and later architectures. Full list of 112 | # supported GPUs is at: 113 | # https://github.com/NVIDIA/open-gpu-kernel-modules#compatible-gpus 114 | # Only available from driver 515.43.04+ 115 | # Currently alpha-quality/buggy, so false is currently the recommended setting. 116 | open = false; 117 | 118 | # Enable the Nvidia settings menu, 119 | # accessible via `nvidia-settings`. 120 | nvidiaSettings = true; 121 | 122 | # Optionally, you may need to select the appropriate driver version for your specific GPU. 123 | package = config.boot.kernelPackages.nvidiaPackages.stable; 124 | }; 125 | } 126 | -------------------------------------------------------------------------------- /workstation/system/boot.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | boot = 5 | { 6 | loader.systemd-boot.enable = true; 7 | loader.efi.canTouchEfiVariables = true; 8 | }; 9 | 10 | fileSystems."/".options = [ "noatime" ]; 11 | } 12 | -------------------------------------------------------------------------------- /workstation/system/environment.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | # TODO: Remove this file and move these options elsewhere 4 | { 5 | nixpkgs.config.allowUnfree = true; 6 | nix.settings.experimental-features = [ "nix-command" "flakes" ]; 7 | } 8 | -------------------------------------------------------------------------------- /workstation/system/network.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | networking = rec 5 | { 6 | hostName = "thelio"; 7 | 8 | enableIPv6 = false; 9 | 10 | networkmanager.enable = true; 11 | 12 | hosts = 13 | { 14 | "127.0.0.1" = 15 | [ 16 | "${hostName}.localdomain" 17 | "${hostName}" 18 | ]; 19 | }; 20 | }; 21 | 22 | services.mullvad-vpn.enable = true; 23 | services.mullvad-vpn.package = pkgs.mullvad-vpn; 24 | /* Required to get DNS working with mullvad. 25 | * https://discourse.nixos.org/t/connected-to-mullvadvpn-but-no-internet-connection/35803/15 26 | */ 27 | networking.resolvconf.enable = false; 28 | 29 | networking.firewall.allowedTCPPorts = [ 30 | 80 31 | 443 32 | 1401 33 | # Minecraft server 34 | 25565 35 | ]; 36 | networking.firewall.allowedUDPPorts = [ 53 1194 1195 1196 1197 1300 1301 1302 1303 1400 ]; 37 | 38 | imports = 39 | [ 40 | ./network/malicious-host.nix 41 | ]; 42 | } 43 | -------------------------------------------------------------------------------- /workstation/system/network/malicious-host.nix: -------------------------------------------------------------------------------- 1 | # Originally from https://github.com/michalrus/dotfiles/blob/master/nixos-config/machines/desktop/modules/malicious-hosts.nix 2 | { config, lib, pkgs, ... }: 3 | 4 | let 5 | danPollock = pkgs.fetchurl 6 | { 7 | url = "http://someonewhocares.org/hosts/zero/hosts"; 8 | # curl http://someonewhocares.org/hosts/zero/hosts | sha256sum 9 | sha256 = "dd5e4f9a4a3b08f8b8c5a45dcb363efeae0df47d8c80b232f8d91fb9c74ee99b"; 10 | }; 11 | in 12 | { 13 | # TODO: Hash isn't working here? Copy the whole thing in? 14 | #networking.extraHosts = builtins.readFile danPollock; 15 | } 16 | -------------------------------------------------------------------------------- /workstation/system/security.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | security.lockKernelModules = false; 5 | 6 | programs.gnupg.agent = 7 | { 8 | enable = true; 9 | enableSSHSupport = true; 10 | }; 11 | 12 | systemd.mounts = 13 | [ 14 | { # Put /tmp on a protected tmpfs. This sucks up more RAM though. 15 | description = "Temporary Directory (/tmp)"; 16 | what = "tmpfs"; 17 | where = "/tmp"; 18 | documentation = 19 | [ 20 | "man:hier(7)" 21 | "https://www.freedesktop.org/wiki/Software/systemd/APIFileSystems" 22 | ]; 23 | before = ["local-fs.target" "umount.target"]; 24 | after = ["swap.target"]; 25 | conflicts = ["umount.target"]; 26 | options = "rw,nosuid,nodev"; 27 | type = "tmpfs"; 28 | 29 | unitConfig = 30 | { 31 | ConditionPathIsSymbolicLink = "!/tmp"; 32 | DefaultDependencies = "no"; 33 | }; 34 | } 35 | ]; 36 | } 37 | -------------------------------------------------------------------------------- /workstation/system/sound.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | services.pipewire.enable = false; 5 | hardware.pulseaudio.enable = true; 6 | hardware.pulseaudio.support32Bit = true; 7 | hardware.pulseaudio.package = pkgs.pulseaudioFull; 8 | 9 | # Disable beep. 10 | boot.blacklistedKernelModules = [ "snd_pcsp" "pcspkr" ]; 11 | } 12 | -------------------------------------------------------------------------------- /workstation/system/usb.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | # Enable USB auto-mounting. 5 | services.gvfs.enable = true; 6 | } 7 | -------------------------------------------------------------------------------- /workstation/system/user.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | security.sudo = 5 | { 6 | enable = true; 7 | wheelNeedsPassword = true; 8 | }; 9 | 10 | # Allow useradd/groupadd imperatively. 11 | users.mutableUsers = true; 12 | } 13 | -------------------------------------------------------------------------------- /workstation/user/jeaye.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | users.users.jeaye = 5 | { 6 | isNormalUser = true; 7 | createHome = true; 8 | group = "users"; 9 | home = "/home/jeaye"; 10 | extraGroups = [ "wheel" "networkmanager" "audio" "ssh" "proc" "docker" ]; 11 | }; 12 | 13 | imports = 14 | [ 15 | #./jeaye/home.nix 16 | ./jeaye/program.nix 17 | ./jeaye/gaming.nix 18 | ./jeaye/desktop.nix 19 | ]; 20 | } 21 | -------------------------------------------------------------------------------- /workstation/user/jeaye/data/dotfiles/Xresources: -------------------------------------------------------------------------------- 1 | ! gruvbox 2 | ! hard contrast: *background: #1d2021 3 | URxvt*background: #282828 4 | ! soft contrast: *background: #32302f 5 | URxvt*foreground: #ebdbb2 6 | ! Black + DarkGrey 7 | URxvt*color0: #282828 8 | URxvt*color8: #928374 9 | ! DarkRed + Red 10 | URxvt*color1: #cc241d 11 | URxvt*color9: #fb4934 12 | ! DarkGreen + Green 13 | URxvt*color2: #98971a 14 | URxvt*color10: #b8bb26 15 | ! DarkYellow + Yellow 16 | URxvt*color3: #d79921 17 | URxvt*color11: #fabd2f 18 | ! DarkBlue + Blue 19 | URxvt*color4: #458588 20 | URxvt*color12: #83a598 21 | ! DarkMagenta + Magenta 22 | URxvt*color5: #b16286 23 | URxvt*color13: #d3869b 24 | ! DarkCyan + Cyan 25 | URxvt*color6: #689d6a 26 | URxvt*color14: #8ec07c 27 | ! LightGrey + White 28 | URxvt*color7: #a89984 29 | URxvt*color15: #ebdbb2 30 | 31 | ! Font 32 | URxvt*termName: rxvt-256color 33 | URxvt*utf8: 1 34 | XTerm*locale: true 35 | URxvt.font: -xos4-terminus-*-*-normal-*-28-*-*-*-*-*-*-* 36 | URxvt.boldFont: -xos4-terminus-*-*-normal-*-28-*-*-*-*-*-*-* 37 | URxvt.italicFont: -xos4-terminus-*-*-normal-*-28-*-*-*-*-*-*-* 38 | URxvt.boldItalicFont: -xos4-terminus-*-*-normal-*-28-*-*-*-*-*-*-* 39 | URxvt*letterSpace: -1 40 | 41 | URxvt.depth: 32 42 | URxvt.geometry: 90x30 43 | URxvt.loginShell: true 44 | URxvt.internalBorder: 0 45 | URxvt.lineSpace: 0 46 | Xft.dpi: 96 47 | Xft.antialias: true 48 | Xft.rgba: rgb 49 | Xft.hinting: true 50 | Xft.hintstyle: hintslight 51 | 52 | ! Scrolling 53 | URxvt*scrollBar: false 54 | ! Lots 55 | URxvt*saveLines: 64000 56 | 57 | ! Bell 58 | URxvt*urgentOnBell: true 59 | 60 | ! Links 61 | URxvt.perl-ext-common: default,matcher 62 | URxvt.url-launcher: /sbin/xdg-open 63 | URxvt.matcher.button: 1 64 | URxvt.keysym.C-Delete: perl:matcher:last 65 | URxvt.keysym.M-Delete: perl:matcher:list 66 | URxvt.colorUL: #cb4b16 67 | 68 | !! Scrolling 69 | ! Do not scroll with output 70 | URxvt*scrollTtyOutput: false 71 | ! Scroll in relation to buffer (with mouse scroll or Shift+Page Up) 72 | URxvt*scrollWithBuffer: true 73 | ! Scroll back to the bottom on keypress 74 | URxvt*scrollTtyKeypress: true 75 | -------------------------------------------------------------------------------- /workstation/user/jeaye/data/dotfiles/bash_profile: -------------------------------------------------------------------------------- 1 | [[ -f ~/.bashrc ]] && . ~/.bashrc 2 | -------------------------------------------------------------------------------- /workstation/user/jeaye/data/dotfiles/bashrc: -------------------------------------------------------------------------------- 1 | # If not running interactively, don't do anything 2 | [[ $- != *i* ]] && return 3 | 4 | # Local binaries 5 | export PATH=~/bin:~/.bin:$PATH 6 | 7 | # Bash options ------------------------------------ 8 | set -o vi # Vi mode 9 | set -o noclobber # do not overwrite files 10 | shopt -s globstar # recursive globbing 11 | shopt -s cdable_vars # if cd arg is not valid, assumes its a var defining a dir 12 | shopt -s cdspell # autocorrects cd misspellings 13 | shopt -s checkwinsize # update the value of LINES and COLUMNS after each command if altered 14 | shopt -s cmdhist # save multi-line commands in history as single line 15 | shopt -s histappend # do not overwrite history 16 | shopt -s dotglob # include dotfiles in pathname expansion 17 | shopt -s expand_aliases # expand aliases 18 | shopt -s extglob # enable extended pattern-matching features 19 | shopt -s progcomp # programmable completion 20 | shopt -s hostcomplete # attempt hostname expansion when @ is at the beginning of a word 21 | shopt -s nocaseglob # pathname expansion will be treated as case-insensitive 22 | 23 | # Have a large history and clean up duplicated lines 24 | unset HISTFILESIZE 25 | HISTSIZE="1000000" 26 | HISTCONTROL=ignoreboth:erasedups 27 | export HISTSIZE 28 | 29 | # Ignore duplicate commands, simple shit, and dangerous shit 30 | export HISTIGNORE="&:ls:[bf]g:exit:clear:cl:history:su:su *:sudo *" 31 | 32 | ## 256 colors 33 | export TERM=rxvt-256color 34 | export EDITOR=nvim 35 | export GPG_TTY=$(tty) 36 | export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01;32:quote=01' 37 | 38 | ## UTF-8 39 | export LC_ALL="en_US.UTF-8" 40 | export LANG="en_US.UTF-8" 41 | export LANGUAGE="en_US.UTF-8" 42 | 43 | # fzf bindings 44 | if command -v fzf-share >/dev/null; 45 | then 46 | source "$(fzf-share)/key-bindings.bash" 47 | fi 48 | 49 | # Rust/Cargo 50 | export PATH=~/.cargo/bin:$PATH 51 | 52 | [ -f ~/.bashrc-alias ] && source ~/.bashrc-alias 53 | [ -f ~/.bashrc-less ] && source ~/.bashrc-less 54 | [ -f ~/.bashrc-prompt ] && source ~/.bashrc-prompt 55 | [ -f ~/.bashrc-secret ] && source ~/.bashrc-secret 56 | -------------------------------------------------------------------------------- /workstation/user/jeaye/data/dotfiles/bashrc-alias: -------------------------------------------------------------------------------- 1 | # Favor verbosity and color 2 | alias cp='cp -vi' 3 | alias mv='mv -vi' 4 | alias rm='rm -vi' 5 | alias mkdir='mkdir -pv' 6 | alias grep='grep --color=auto' 7 | alias cl='clear' 8 | alias ls='ls --color=auto' 9 | alias less='less -R' 10 | alias vim='vim -p' 11 | alias gvim='gvim -p' 12 | alias rn='react-native' 13 | alias mplayer='mpv' 14 | alias ps='ps ax | grep' 15 | alias g='git' 16 | alias fail='tail -f' 17 | 18 | # Functions 19 | function weather 20 | { curl wttr.in/${1:-Burlingame}; } 21 | 22 | function define 23 | { dict "$1" | less -R; } 24 | 25 | function irc 26 | { ssh -t jeaye@pastespace.org "tmux attach || tmux new"; } 27 | 28 | function cd 29 | { 30 | if [ $# -eq 1 ]; 31 | then 32 | command cd "$1" 33 | else 34 | command cd ~ 35 | fi 36 | pwd >| ~/.last-directory 37 | } 38 | 39 | function cd-last-directory 40 | { 41 | last=$(cat ~/.last-directory 2>/dev/null || echo ~) 42 | command cd "$last" 43 | } 44 | -------------------------------------------------------------------------------- /workstation/user/jeaye/data/dotfiles/bashrc-less: -------------------------------------------------------------------------------- 1 | # Colors 2 | default=$(tput sgr0) 3 | red=$(tput setaf 1) 4 | green=$(tput setaf 2) 5 | purple=$(tput setaf 5) 6 | orange=$(tput setaf 9) 7 | 8 | # Less colors for man pages 9 | export PAGER="less -R" 10 | # Begin blinking 11 | export LESS_TERMCAP_mb=$red 12 | # Begin bold 13 | export LESS_TERMCAP_md=$orange 14 | # End mode 15 | export LESS_TERMCAP_me=$default 16 | # End standout-mode 17 | export LESS_TERMCAP_se=$default 18 | # Begin standout-mode - info box 19 | export LESS_TERMCAP_so=$purple 20 | # End underline 21 | export LESS_TERMCAP_ue=$default 22 | # Begin underline 23 | export LESS_TERMCAP_us=$green 24 | -------------------------------------------------------------------------------- /workstation/user/jeaye/data/dotfiles/bashrc-prompt: -------------------------------------------------------------------------------- 1 | # Colors 2 | default=$(tput sgr0) 3 | red=$(tput setaf 1) 4 | green=$(tput setaf 2) 5 | yellow=$(tput setaf 3) 6 | blue=$(tput setaf 39) 7 | purple=$(tput setaf 5) 8 | cyan=$(tput setaf 6) 9 | orange=$(tput setaf 9) 10 | 11 | # PS1 prompt 12 | git_branch() 13 | { 14 | if git rev-parse --git-dir >/dev/null 2>&1 15 | then 16 | branch=`git symbolic-ref --short HEAD 2>/dev/null` 17 | if [ -z "$branch" ] 18 | then 19 | branch="DETACHED" 20 | color=${red} 21 | elif git diff --quiet 2>/dev/null >&2 22 | then 23 | if [ -n "`git status -s --untracked-files=no 2>/dev/null`" ] 24 | then 25 | color=${yellow} 26 | else 27 | headRev=`git rev-list --max-count=1 HEAD 2>/dev/null` 28 | upstreamBranch=`git remote 2>/dev/null`/$branch 29 | upstreamRev=`git rev-list --max-count=1 $upstreamBranch 2>/dev/null` 30 | if [ "$upstreamRev" = "$headRev" ] 31 | then 32 | color=${green} 33 | else 34 | color=${blue} 35 | fi 36 | fi 37 | else 38 | color=${red} 39 | fi 40 | else 41 | return 0 42 | fi 43 | echo "[${color}$branch${default}]" 44 | } 45 | last_error() 46 | { 47 | if [[ $? == 0 ]]; 48 | then 49 | echo "(${green}✓${default})" 50 | else 51 | echo "(${red}✗${default})" 52 | fi 53 | } 54 | current_time() 55 | { date "+%H:%M:%S"; } 56 | PS1='${default}┌─$(last_error)[${cyan}\u${default}@${purple}\h${default}]─[${green}\w${default}][${orange}$(current_time)${default}]$(git_branch)${default}$(tput bel)\n└──╼ ' 57 | -------------------------------------------------------------------------------- /workstation/user/jeaye/data/dotfiles/bin/define: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | wn $1 -over 4 | -------------------------------------------------------------------------------- /workstation/user/jeaye/data/dotfiles/bin/i3data: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | i3status | (read line && echo $line && read line && echo $line && while : 4 | do 5 | read line 6 | #artist=$(cmus-remote -Q | grep ' artist ' | cut -d ' ' -f3-) 7 | #song=$(cmus-remote -Q | grep title | cut -d ' ' -f3-) 8 | #music="${artist} - ${song}" 9 | music=$(mpc current -f "%artist% [/ %composer% ]/ %title%") 10 | data="[{ \"full_text\": \"${music}\" }," 11 | echo "${line/[/$data}" || exit 1 12 | done) 13 | -------------------------------------------------------------------------------- /workstation/user/jeaye/data/dotfiles/bin/lock: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | i3lock -e -c 002b36 4 | -------------------------------------------------------------------------------- /workstation/user/jeaye/data/dotfiles/bin/super-nice: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eu 4 | 5 | echo "Setting priority for $1" 6 | sudo renice -10 $1 7 | sudo ionice -c 2 -n 0 -p $1 8 | -------------------------------------------------------------------------------- /workstation/user/jeaye/data/dotfiles/bin/upload: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eu -o pipefail 4 | 5 | scp -r "$@" http-upload@upload.jeaye.com:queue/ 6 | 7 | for f in "$@"; 8 | do 9 | echo https://upload.jeaye.com/tmp/$(basename "$f") 10 | done 11 | -------------------------------------------------------------------------------- /workstation/user/jeaye/data/dotfiles/bin/youtube-dl-audio: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eu -o pipefail 4 | 5 | #youtube-dl -x --audio-format "best" --audio-quality 0 "$1" 6 | youtube-dl -x --audio-format "best" --audio-quality 0 "$1" 7 | -------------------------------------------------------------------------------- /workstation/user/jeaye/data/dotfiles/config/i3/config: -------------------------------------------------------------------------------- 1 | # i3 config file (v4) 2 | 3 | set $mod Mod4 4 | 5 | # font for window titles. ISO 10646 = Unicode 6 | #font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1 7 | font xft:terminus 8 | 9 | # Use Mouse+$mod to drag floating windows to their wanted position 10 | floating_modifier $mod 11 | 12 | # setup default environment 13 | bindsym $mod+Shift+e exec i3-msg 'workspace 1; exec firefox; workspace 2; exec urxvt; workspace 7; layout tabbed; exec urxvt; exec signal-desktop; workspace 8; exec discord; workspace 9; exec thunderbird; workspace 10; exec pavucontrol; nop ' 14 | 15 | # start a terminal 16 | bindsym $mod+Return exec urxvt 17 | bindsym $mod+Shift+Return exec "urxvt -cd $(cat ~/.last-directory 2>/dev/null || echo ~)" 18 | 19 | # start a browser 20 | bindsym $mod+Shift+f exec firefox 21 | 22 | bindsym $mod+Shift+g exec lock 23 | 24 | for_window [class="(?i)gvim"] client.focused #000000 #000000 #000000 #000000 25 | for_window [class="plasmashell"] floating window 26 | 27 | # screenshot 28 | bindsym $mod+Shift+s exec import -window root ~/screen-shot-$(date +'%Y-%m-%d-%H-%M-%S').png 29 | 30 | # music control 31 | #bindsym XF86AudioPrev exec cmus-remote -r 32 | #bindsym XF86AudioNext exec cmus-remote -n 33 | #bindsym XF86AudioPause exec cmus-remote -u 34 | #bindsym XF86AudioMute exec cmus-remote -u 35 | #bindsym XF86AudioRaiseVolume exec cmus-remote -v +10 36 | #bindsym XF86AudioLowerVolume exec cmus-remote -v -10 37 | 38 | bindsym XF86AudioPrev exec mpc prev 39 | bindsym XF86AudioNext exec mpc next 40 | bindsym XF86AudioPause exec mpc toggle 41 | bindsym XF86AudioRaiseVolume exec mpc volume +10 42 | bindsym XF86AudioLowerVolume exec mpc volume -10 43 | 44 | # kill focused window 45 | bindsym $mod+x kill 46 | 47 | # start dmenu (a program launcher) 48 | bindsym $mod+d exec dmenu_run -nb '#282828' -nf '#928374' -sb '#282828' -sf '#d65d0e' 49 | 50 | # change focus 51 | bindsym $mod+j focus down 52 | bindsym $mod+k focus up 53 | bindsym $mod+l focus right 54 | bindsym $mod+h focus left 55 | 56 | # scratchpad 57 | bindsym $mod+o move scratchpad 58 | bindsym $mod+p scratchpad show 59 | 60 | # alternatively, you can use the cursor keys: 61 | bindsym $mod+Left focus left 62 | bindsym $mod+Down focus down 63 | bindsym $mod+Up focus up 64 | bindsym $mod+Right focus right 65 | 66 | # move focused window 67 | bindsym $mod+Shift+J move down 68 | bindsym $mod+Shift+K move up 69 | bindsym $mod+Shift+L move right 70 | bindsym $mod+Shift+H move left 71 | 72 | # alternatively, you can use the cursor keys: 73 | bindsym $mod+Shift+Left move left 74 | bindsym $mod+Shift+Down move down 75 | bindsym $mod+Shift+Up move up 76 | bindsym $mod+Shift+Right move right 77 | 78 | # split in horizontal orientation 79 | #bindsym $mod+h split h 80 | 81 | # split in vertical orientation 82 | bindsym $mod+v split v 83 | 84 | # enter fullscreen mode for the focused container 85 | bindsym $mod+f fullscreen 86 | 87 | # change container layout (stacked, tabbed, default) 88 | bindsym $mod+s layout stacking 89 | bindsym $mod+w layout tabbed 90 | bindsym $mod+e layout default 91 | 92 | # toggle tiling / floating 93 | bindsym $mod+Shift+space floating toggle 94 | 95 | # change focus between tiling / floating windows 96 | #bindsym $mod+space focus mode_toggle 97 | 98 | # focus the parent container 99 | bindsym $mod+a focus parent 100 | 101 | # switch to workspace 102 | bindsym $mod+1 workspace 1 103 | bindsym $mod+2 workspace 2 104 | bindsym $mod+3 workspace 3 105 | bindsym $mod+4 workspace 4 106 | bindsym $mod+5 workspace 5 107 | bindsym $mod+6 workspace 6 108 | bindsym $mod+7 workspace 7 109 | bindsym $mod+8 workspace 8 110 | bindsym $mod+9 workspace 9 111 | bindsym $mod+0 workspace 10 112 | 113 | # move focused container to workspace 114 | bindsym $mod+Shift+exclam move container to workspace 1 115 | bindsym $mod+Shift+at move container to workspace 2 116 | bindsym $mod+Shift+numbersign move container to workspace 3 117 | bindsym $mod+Shift+dollar move container to workspace 4 118 | bindsym $mod+Shift+percent move container to workspace 5 119 | bindsym $mod+Shift+asciicircum move container to workspace 6 120 | bindsym $mod+Shift+ampersand move container to workspace 7 121 | bindsym $mod+Shift+asterisk move container to workspace 8 122 | bindsym $mod+Shift+parenleft move container to workspace 9 123 | bindsym $mod+Shift+parenright move container to workspace 10 124 | 125 | # reload the configuration file 126 | bindsym $mod+Shift+C reload 127 | # restart i3 inplace (preserves your layout/session, can be used to upgrade i3) 128 | bindsym $mod+Shift+R restart 129 | # exit i3 (logs you out of your X session) 130 | #bindsym $mod+Shift+E exit 131 | 132 | # resize window (you can also use the mouse for that) 133 | mode "resize" { 134 | # These bindings trigger as soon as you enter the resize mode 135 | 136 | # Pressing left will shrink the window’s width. 137 | # Pressing right will grow the window’s width. 138 | # Pressing up will shrink the window’s height. 139 | # Pressing down will grow the window’s height. 140 | bindsym k resize shrink height 10 px or 10 ppt 141 | bindsym j resize grow height 10 px or 10 ppt 142 | bindsym h resize shrink width 10 px or 10 ppt 143 | bindsym l resize grow width 10 px or 10 ppt 144 | 145 | # same bindings, but for the arrow keys 146 | bindsym 113 resize shrink width 10 px or 10 ppt 147 | bindsym 116 resize grow height 10 px or 10 ppt 148 | bindsym 111 resize shrink height 10 px or 10 ppt 149 | bindsym 114 resize grow width 10 px or 10 ppt 150 | 151 | # back to normal: Enter or Escape 152 | bindsym Return mode "default" 153 | bindsym Escape mode "default" 154 | } 155 | 156 | bindsym $mod+r mode "resize" 157 | 158 | # Window colors: 159 | # class border backgr. text indicator 160 | client.focused #222222 #79740e #ffffff #b8bb26 161 | client.focused_inactive #222222 #5f676a #ffffff #484e50 162 | client.unfocused #222222 #222222 #888888 #292d2e 163 | client.urgent #222222 #859900 #000000 #859900 164 | for_window [class="^.*"] border pixel 1 165 | 166 | # Start i3bar to display a workspace bar (plus the system information i3status 167 | # finds out, if available) 168 | bar { 169 | status_command ~/.bin/i3data 170 | position bottom 171 | workspace_buttons yes 172 | #mode hide 173 | font pango:DejaVu Sans Mono 14 174 | 175 | colors { 176 | #hsetroot -solid "#282828" 177 | background #282828 178 | statusline #928374 179 | separator #d65d0e 180 | 181 | focused_workspace #a89984 #282828 #ffffff 182 | active_workspace #222222 #d65d0e #ffffff 183 | inactive_workspace #222222 #111111 #888888 184 | urgent_workspace #2f343a #d65d0e #ffffff 185 | } 186 | } 187 | 188 | -------------------------------------------------------------------------------- /workstation/user/jeaye/data/dotfiles/gitconfig: -------------------------------------------------------------------------------- 1 | [user] 2 | name = jeaye 3 | email = contact@jeaye.com 4 | [color] 5 | all = true 6 | ui = true 7 | branch = auto 8 | diff = auto 9 | status = auto 10 | [color "branch"] 11 | current = yellow reverse 12 | local = yellow 13 | remote = green 14 | [color "diff"] 15 | meta = yellow bold 16 | frag = magenta bold 17 | old = red bold 18 | new = green bold 19 | [color "status"] 20 | added = green 21 | changed = red 22 | untracked = yellow 23 | [alias] 24 | po = push origin 25 | pu = push upstream 26 | c = commit 27 | cp = cherry-pick 28 | ch = checkout 29 | st = status --column -sb 30 | sup = submodule update --recursive --init 31 | d = difftool --ignore-submodules 32 | di = difftool --tool=vim_ignore_whitespace -w --ignore-submodules 33 | ds = difftool --stat --ignore-submodules 34 | ll = log --pretty=oneline --graph --abbrev-commit --decorate --topo-order 35 | dp = difftool --tool=patch --ignore-submodules --minimal -w 36 | clr = clone --recursive 37 | find = log --pickaxe-all -S 38 | fpull = "!f(){ git pull \"$1\" \"$2\" && git fat pull; };f" 39 | fpush = "!f(){ git push \"$1\" \"$2\" && git fat push; };f" 40 | reset-time = "!f(){ touch -camft $(git log --date=iso --pretty=format:%cd -1 HEAD -- \"$1\" | sed 's/-//g;s/ //;s/://;s/:/./' | cut -d' ' -f1) \"$1\"; };f" 41 | deploy = push heroku 42 | [merge] 43 | keepBackup = false 44 | tool = custom_merge 45 | renamelimit = 100000 46 | [mergetool "custom_merge"] 47 | cmd = p4merge "$BASE" "$LOCAL" "$REMOTE" "$MERGED" 48 | keepTemporaries = false 49 | trustExitCode = false 50 | keepBackup = false 51 | [diff] 52 | tool = vim 53 | renamelimit = 100000 54 | [difftool "vim"] 55 | cmd = vim -d -R "$LOCAL" "$REMOTE" 56 | [difftool "vim_ignore_whitespace"] 57 | cmd = vim -c 'set diffopt+=iwhite' -d -R "$LOCAL" "$REMOTE" 58 | [difftool] 59 | prompt = false 60 | [push] 61 | default = simple 62 | [core] 63 | pager = less -R 64 | excludesfile = /home/jeaye/.gitignore 65 | [gist] 66 | private = yes 67 | browse = no 68 | [filter "lfs"] 69 | required = true 70 | clean = git-lfs clean -- %f 71 | smudge = git-lfs smudge -- %f 72 | process = git-lfs filter-process 73 | [commit] 74 | gpgsign = true 75 | [stash] 76 | showPatch = 1 77 | [pager] 78 | log = less 79 | show = less -R 80 | diff = less -R 81 | -------------------------------------------------------------------------------- /workstation/user/jeaye/data/dotfiles/gitignore: -------------------------------------------------------------------------------- 1 | # Vim 2 | *~ 3 | *.swp 4 | *.swo 5 | 6 | # GDB 7 | .gdbinit 8 | -------------------------------------------------------------------------------- /workstation/user/jeaye/data/dotfiles/i3status.conf: -------------------------------------------------------------------------------- 1 | # i3status configuration file. 2 | # see "man i3status" for documentation. 3 | 4 | # It is important that this file is edited as UTF-8. 5 | # The following line should contain a sharp s: 6 | # ß 7 | # If the above line is not correctly displayed, fix your editor first! 8 | 9 | general { 10 | output_format = "i3bar" 11 | colors = true 12 | interval = 5 13 | } 14 | 15 | #order += "ipv6" 16 | #order += "disk /" 17 | #order += "run_watch DHCP" 18 | #order += "run_watch VPN" 19 | order += "volume master" 20 | order += "wireless wlan0" 21 | #order += "ethernet eth0" 22 | order += "cpu_temperature 0" 23 | order += "battery 0" 24 | order += "load" 25 | order += "tztime local" 26 | 27 | volume master { 28 | format = "V: %volume" 29 | device = "default" 30 | mixer = "PCM" 31 | mixer_idx = 0 32 | } 33 | 34 | wireless wlan0 { 35 | format_up = "W: (%quality at %essid) %ip" 36 | format_down = "W: down" 37 | color_bad = "#657b83" 38 | } 39 | 40 | ethernet eth0 { 41 | # if you use %speed, i3status requires root privileges 42 | format_up = "E: %ip (%speed)" 43 | format_down = "E: down" 44 | } 45 | 46 | battery 0 { 47 | format = "%status %percentage %remaining" 48 | } 49 | 50 | run_watch DHCP { 51 | pidfile = "/var/run/dhclient*.pid" 52 | } 53 | 54 | run_watch VPN { 55 | pidfile = "/var/run/vpnc/pid" 56 | } 57 | 58 | tztime local { 59 | format = "%Y-%m-%d %a %H:%M:%S" 60 | } 61 | 62 | load { 63 | format = "%1min" 64 | } 65 | 66 | disk "/" { 67 | format = "%avail" 68 | } 69 | 70 | cpu_temperature 0 { 71 | format = " ± %degrees°" 72 | path = "/sys/devices/platform/coretemp.0/hwmon/hwmon2/temp1_input" 73 | max_threshold = 95 74 | } 75 | -------------------------------------------------------------------------------- /workstation/user/jeaye/data/dotfiles/lein/profiles.clj: -------------------------------------------------------------------------------- 1 | {:user {:plugins [[lein-ancient "0.6.10"] 2 | [lein-pprint "1.1.1"] 3 | [cider/cider-nrepl "0.13.0"] 4 | [cljfmt "0.5.1"] 5 | [venantius/ultra "0.5.0"] 6 | [lein-localrepo "0.5.3"]]}} 7 | -------------------------------------------------------------------------------- /workstation/user/jeaye/data/dotfiles/mpv/mpv.conf: -------------------------------------------------------------------------------- 1 | vo=opengl-hq 2 | sub-codepage=utf8 3 | softvol-max=300 4 | -------------------------------------------------------------------------------- /workstation/user/jeaye/data/dotfiles/tmux.conf: -------------------------------------------------------------------------------- 1 | ## 256 colors, please 2 | set -g default-terminal "screen-256color" 3 | 4 | ## Mouse scrolling 5 | #set -g mode-mouse on 6 | 7 | ## Vim 8 | set-window-option -g mode-keys vi 9 | bind-key -t vi-copy 'v' begin-selection 10 | bind-key -t vi-copy 'y' copy-selection 11 | bind P paste-buffer 12 | 13 | #### COLOR (Solarized dark) 14 | 15 | # default statusbar colors 16 | set-option -g status-bg black #base02 17 | set-option -g status-fg yellow #yellow 18 | set-option -g status-attr default 19 | 20 | # default window title colors 21 | set-window-option -g window-status-fg brightblue #base0 22 | set-window-option -g window-status-bg default 23 | #set-window-option -g window-status-attr dim 24 | 25 | # active window title colors 26 | set-window-option -g window-status-current-fg brightred #orange 27 | set-window-option -g window-status-current-bg default 28 | #set-window-option -g window-status-current-attr bright 29 | 30 | # pane border 31 | set-option -g pane-border-fg black #base02 32 | set-option -g pane-active-border-fg brightgreen #base01 33 | 34 | # message text 35 | set-option -g message-bg black #base02 36 | set-option -g message-fg brightred #orange 37 | 38 | # pane number display 39 | set-option -g display-panes-active-colour blue #blue 40 | set-option -g display-panes-colour brightred #orange 41 | 42 | # clock 43 | set-window-option -g clock-mode-colour green #green 44 | 45 | # time to recognize esc 46 | set -sg escape-time 0 47 | -------------------------------------------------------------------------------- /workstation/user/jeaye/data/dotfiles/xinitrc: -------------------------------------------------------------------------------- 1 | # Disable bell. 2 | xset -b 3 | 4 | # Acknowledge some more X settings. 5 | xrdb -merge ~/.Xresources 6 | 7 | # Nice background color. 8 | hsetroot -solid "#282828" 9 | 10 | # Disable laptop monitor. 11 | if [[ $(xrandr | grep "HDMI-0 connected") ]]; 12 | then 13 | xrandr --output LVDS --off 14 | xrandr --output DP-0 --off 15 | xrandr --output HDMI-0 --dpi 96 16 | fi 17 | 18 | # Set keyboard layout; toggle with alt + shift. 19 | #setxkbmap -layout us,dvp -option grp:alt_shift_toggle 20 | 21 | # Lock the screen, if it's idle. 22 | xautolock -time 10 -locker "~/.bin/lock" -secure & 23 | 24 | # Remove blue light at night 25 | redshift & 26 | 27 | # Skype uses the GNOME keyring 28 | #eval $(/usr/bin/gnome-keyring-daemon --start --components=pkcs11,secrets,ssh) 29 | #export SSH_AUTH_SOCK 30 | 31 | mpd & 32 | 33 | # The X session dies when i3 exits. 34 | exec i3 35 | -------------------------------------------------------------------------------- /workstation/user/jeaye/desktop.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, expr, buildVM, ... }: 2 | 3 | let 4 | iconTheme = pkgs.breeze-icons.out; 5 | themeEnv = 6 | '' 7 | # GTK3: add /etc/xdg/gtk-3.0 to search path for settings.ini 8 | # We use /etc/xdg/gtk-3.0/settings.ini to set the icon and theme name for GTK 3 9 | export XDG_CONFIG_DIRS="/etc/xdg:$XDG_CONFIG_DIRS" 10 | 11 | # GTK2 theme + icon theme 12 | export GTK2_RC_FILES=${pkgs.writeText "iconrc" ''gtk-icon-theme-name="breeze"''}:${pkgs.breeze-gtk}/share/themes/Breeze/gtk-2.0/gtkrc:$GTK2_RC_FILES 13 | 14 | # SVG loader for pixbuf (needed for GTK svg icon themes) 15 | export GDK_PIXBUF_MODULE_FILE=$(echo ${pkgs.librsvg.out}/lib/gdk-pixbuf-2.0/*/loaders.cache) 16 | 17 | # QT5: convince it to use our preferred style 18 | export QT_STYLE_OVERRIDE=kvantum 19 | ''; 20 | in 21 | { 22 | 23 | environment.extraInit = 24 | '' 25 | ${themeEnv} 26 | 27 | # These are the defaults, but some applications are buggy so we set them 28 | # here anyway. 29 | export XDG_CONFIG_HOME=$HOME/.config 30 | export XDG_DATA_HOME=$HOME/.local/share 31 | export XDG_CACHE_HOME=$HOME/.cache 32 | ''; 33 | 34 | # QT4/5 global theme 35 | environment.etc."xdg/Trolltech.conf" = 36 | { 37 | text = 38 | '' 39 | [Qt] 40 | style=Breeze 41 | ''; 42 | mode = "444"; 43 | }; 44 | 45 | # GTK3 global theme (widget and icon theme) 46 | environment.etc."xdg/gtk-3.0/settings.ini" = 47 | { 48 | text = 49 | '' 50 | [Settings] 51 | gtk-icon-theme-name=breeze 52 | gtk-theme-name=Breeze-gtk 53 | ''; 54 | mode = "444"; 55 | }; 56 | 57 | users.users.jeaye = 58 | { 59 | packages = with pkgs; 60 | [ 61 | redshift 62 | imagemagick 63 | flameshot 64 | xfce.thunar 65 | # Needed for thumbnails in pcmanfm 66 | xfce.tumbler 67 | # Allows pcmanfm to recognize different file types 68 | shared-mime-info 69 | 70 | # Qt theme 71 | breeze-qt5 72 | breeze-gtk 73 | 74 | # Icons (Main) 75 | iconTheme 76 | 77 | # Icons (Fallback) 78 | gnome.adwaita-icon-theme 79 | 80 | # Qt Style tooling 81 | libsForQt5.qtstyleplugin-kvantum 82 | libsForQt5.qt5ct 83 | themechanger 84 | ]; 85 | }; 86 | 87 | nixpkgs.config.qt5 = 88 | { 89 | enable = true; 90 | platformTheme = "qt5ct"; 91 | }; 92 | environment.variables.QT_QPA_PLATFORMTHEME = "qt5ct"; 93 | 94 | # Make applications find files in /share 95 | environment.pathsToLink = [ "/share" ]; 96 | } 97 | -------------------------------------------------------------------------------- /workstation/user/jeaye/gaming.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, lib, ... }: 2 | 3 | { 4 | #users.users.jeaye = 5 | #{ 6 | # packages = with pkgs; 7 | # [ 8 | # steam 9 | # ]; 10 | #}; 11 | programs.steam = 12 | { 13 | enable = true; 14 | # TODO: Enable once this is live. 15 | #protontricks.enable = true; 16 | }; 17 | 18 | # Needed for Rocket League. 19 | nixpkgs.config.permittedInsecurePackages = 20 | [ 21 | "openssl-1.1.1w" 22 | ]; 23 | nixpkgs.overlays = [ 24 | (final: prev: { 25 | steam = prev.steam.override ({ extraPkgs ? pkgs': [], ... }: { 26 | extraPkgs = pkgs': (extraPkgs pkgs') ++ (with pkgs'; [ 27 | openssl_1_1 28 | protontricks 29 | ]); 30 | }); 31 | }) 32 | ]; 33 | 34 | programs.gamemode.enable = true; 35 | } 36 | -------------------------------------------------------------------------------- /workstation/user/jeaye/home.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, lib, ... }: 2 | 3 | let 4 | # TODO: Use readDir + map to get these automatically. 5 | dotfiles = 6 | [ 7 | "bash_profile" "bashrc" "bashrc-alias" "bashrc-less" "bashrc-prompt" 8 | "config/i3" 9 | "i3status.conf" 10 | "gitconfig" 11 | "gitignore" 12 | "xinitrc" "Xresources" 13 | "lein/profiles.clj" 14 | "mpv/mpv.conf" 15 | "tmux.conf" 16 | "bin" 17 | ]; 18 | make-dotfile = file: 19 | { 20 | source = ./data/dotfiles + "/${file}"; 21 | target = "user/jeaye/.${file}"; 22 | }; 23 | in 24 | { 25 | nixpkgs.config.packageOverrides = pkgs: 26 | { 27 | jeaye-vimrc = pkgs.callPackage ./pkg/vimrc.nix { }; 28 | }; 29 | 30 | # TODO: Neovim links 31 | #environment.etc = 32 | #[ 33 | # ## Vim 34 | # { 35 | # source = pkgs.jeaye-vimrc + "/layer"; 36 | # target = "user/jeaye/.vim/layer"; 37 | # } 38 | # { 39 | # source = pkgs.jeaye-vimrc + "/build"; 40 | # target = "user/jeaye/.vim/build"; 41 | # } 42 | # { 43 | # source = pkgs.jeaye-vimrc + "/vimrc"; 44 | # target = "user/jeaye/.vimrc"; 45 | # } 46 | # ## X 47 | # { 48 | # source = ./data/dotfiles/xinitrc; 49 | # target = "user/jeaye/.xsession"; 50 | # } 51 | #] ++ (map make-dotfile dotfiles); 52 | 53 | system.activationScripts = 54 | { 55 | # The permissions of ~/.vim need to be fudged, since it was made by Nix. 56 | jeaye-vimrc = 57 | { 58 | deps = []; 59 | text = 60 | '' 61 | vim_dirs=$(echo /etc/user/jeaye/.vim/{autoload,plugged}) 62 | mkdir -p $vim_dirs 63 | chown -R jeaye:users $vim_dirs 64 | ''; 65 | }; 66 | 67 | # More fudging to account for environment.etc creations. 68 | jeaye-dotfiles = 69 | { 70 | deps = []; 71 | text = 72 | '' 73 | dotfile_dirs=$(echo /etc/user/jeaye/.{config,lein}) 74 | mkdir -p $dotfile_dirs 75 | chown -R jeaye:users $dotfile_dirs 76 | ''; 77 | }; 78 | }; 79 | } 80 | -------------------------------------------------------------------------------- /workstation/user/jeaye/pkg/vimrc.nix: -------------------------------------------------------------------------------- 1 | { stdenv, fetchgit }: 2 | 3 | stdenv.mkDerivation rec 4 | { 5 | name = "jeaye-vimrc"; 6 | src = fetchgit 7 | { 8 | url = "https://github.com/jeaye/vimrc.git"; 9 | deepClone = true; 10 | rev = "c718665"; 11 | sha256 = "052hy2shkldqnkgr9vijadrwns5skgplf5027hrd5avp7vw65z42"; 12 | }; 13 | installPhase = 14 | '' 15 | mkdir -p $out 16 | cp -r $src/* $out/ 17 | ''; 18 | } 19 | -------------------------------------------------------------------------------- /workstation/user/jeaye/program.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, lib, ... }: 2 | 3 | let pkgsUnstable = import 4 | ( 5 | fetchTarball https://github.com/NixOS/nixpkgs/archive/master.tar.gz 6 | ) 7 | { }; 8 | in 9 | { 10 | users.users.jeaye = 11 | { 12 | packages = with pkgs; 13 | [ 14 | ## Security 15 | pinentry 16 | gnupg 17 | keepassxc 18 | 19 | ## Editing 20 | # Noice requires nvim >=0.11 21 | pkgsUnstable.neovim 22 | fzf 23 | xclip 24 | flameshot 25 | 26 | ## Browsing 27 | firefox 28 | chromium 29 | 30 | ## Calendar 31 | thunderbird 32 | 33 | ## Media 34 | clementine 35 | mpv 36 | pavucontrol 37 | transmission_4-gtk 38 | pkgsUnstable.qbittorrent 39 | # For querying the currently playing media (MPRIS). 40 | playerctl 41 | 42 | ## Chat 43 | pkgsUnstable.signal-desktop 44 | 45 | ## Dictionary 46 | dict 47 | dictdDBs.wordnet 48 | 49 | ## Development 50 | man-pages 51 | man-pages-posix 52 | # For debugging nix builds with breakpointHook 53 | cntr 54 | distrobox 55 | # For distrobox X sharing, needed for clipboard sharing 56 | xorg.xhost 57 | pinentry-curses 58 | clojure 59 | clojure-lsp 60 | rlwrap 61 | leiningen 62 | tree 63 | clang 64 | # clangd 65 | clang-tools 66 | cmake 67 | ninja 68 | gnumake 69 | mdbook 70 | asciinema 71 | # p4merge 72 | p4v 73 | 74 | ## Art 75 | inkscape 76 | gimp 77 | blender 78 | ]; 79 | }; 80 | 81 | nixpkgs.overlays = [ 82 | (self: super: { 83 | mpv = super.mpv.override { 84 | scripts = [ self.mpvScripts.mpris ]; 85 | }; 86 | }) 87 | ]; 88 | 89 | #nixpkgs.config.packageOverrides = self : rec { 90 | # blender = self.blender.override { 91 | # cudaSupport = true; 92 | # }; 93 | #}; 94 | 95 | documentation.dev.enable = true; 96 | } 97 | --------------------------------------------------------------------------------