diff --git a/bash.nix b/bash.nix new file mode 100644 index 0000000..cd7b65d --- /dev/null +++ b/bash.nix @@ -0,0 +1,44 @@ +{ config, lib, pkgs, ... }: + +let + helpers = pkgs.writeText "bash.helpers" + (builtins.readFile ./static/bash/bash.helpers); + + colors = + pkgs.writeText "bash.colors" (builtins.readFile ./static/bash/bash.colors); + + env = pkgs.writeText "bash.env" (builtins.readFile ./static/bash/bash.env); + +in { + config.programs.bash = { + shellAliases = { + ll = "ls $LS_OPTIONS -alF"; + l = "ls $LS_OPTIONS -CF"; + la = "ls $LS_OPTIONS -A"; + ".." = "cd .."; + "..." = "cd ../.."; + rm = "rm --one-file-system --preserve-root"; + }; + + shellInit = '' + if [ -d $HOME/bin ]; then + PATH="$HOME/bin:$PATH" + fi + ''; + + interactiveShellInit = '' + case $TERM in + screen|xterm*|rxvt*) + export LS_OPTIONS="--color=auto" + ;; + *) + export LS_OPTIONS="" + ;; + esac + + . ${colors} + . ${helpers} + . ${env} + ''; + }; +} diff --git a/config/local.nix b/config/default.nix similarity index 95% rename from config/local.nix rename to config/default.nix index 7c2b692..cd6fee6 100644 --- a/config/local.nix +++ b/config/default.nix @@ -1,7 +1,6 @@ { lib, config, pkgs, ... }: -with lib; -{ +with lib; { imports = [ ./fudo/acme-for-hostname.nix ./fudo/authentication.nix @@ -13,6 +12,7 @@ with lib; ./fudo/garbage-collector.nix ./fudo/git.nix ./fudo/grafana.nix + ./fudo/ipfs.nix ./fudo/kdc.nix ./fudo/ldap.nix ./fudo/local-network.nix diff --git a/config/fudo/ipfs.nix b/config/fudo/ipfs.nix new file mode 100644 index 0000000..23497dc --- /dev/null +++ b/config/fudo/ipfs.nix @@ -0,0 +1,71 @@ +{ config, lib, pkgs, ... }: + +with lib; +let + cfg = config.fudo.ipfs; + + user-group-entry = group: user: + nameValuePair user { extraGroups = [ group ]; }; + + user-home-entry = ipfs-path: user: + nameValuePair user { home.sessionVariables = { IPFS_PATH = ipfs-path; }; }; + +in { + options.fudo.ipfs = with types; { + enable = mkEnableOption "Fudo IPFS"; + + users = mkOption { + type = listOf str; + description = "List of users with IPFS access."; + default = [ ]; + }; + + user = mkOption { + type = str; + description = "User as which to run IPFS user."; + default = "ipfs"; + }; + + group = mkOption { + type = str; + description = "Group as which to run IPFS user."; + default = "ipfs"; + }; + + api-address = mkOption { + type = str; + description = "Address on which to listen for requests."; + default = "/ip4/127.0.0.1/tcp/5001"; + }; + + automount = mkOption { + type = bool; + description = "Whether to automount /ipfs and /ipns on boot."; + default = true; + }; + + data-dir = mkOption { + type = str; + description = "Path to store data for IPFS."; + default = "/var/lib/ipfs"; + }; + }; + + config = mkIf cfg.enable { + + users.users = listToAttrs (map (user-group-entry cfg.group) cfg.users); + + services.ipfs = { + enable = true; + apiAddress = cfg.api-address; + autoMount = cfg.automount; + enableGC = true; + user = cfg.user; + group = cfg.group; + dataDir = cfg.data-dir; + }; + + home-manager.users = + listToAttrs (map (user-home-entry cfg.data-dir) cfg.users); + }; +} diff --git a/config/fudo/mail-container.nix b/config/fudo/mail-container.nix index c918116..5cae00e 100644 --- a/config/fudo/mail-container.nix +++ b/config/fudo/mail-container.nix @@ -1,5 +1,4 @@ -{ config, lib, ... }: - +{ lib, config, ... }: with lib; let cfg = config.fudo.mail-server; @@ -71,9 +70,12 @@ in rec { proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; ''; - trusted-network-string = optionalString ((length fudo-cfg.local-networks) > 0) + trusted-network-string = + optionalString ((length fudo-cfg.local-networks) > 0) (concatStringsSep "\n" - (map (network: "allow ${network};") fudo-cfg.local-networks)) + "\ndeny all;"; + (map (network: "allow ${network};") fudo-cfg.local-networks)) + '' + + deny all;''; in { "${cfg.hostname}" = { @@ -136,13 +138,9 @@ in rec { config = { config, pkgs, ... }: { - environment.systemPackages = with pkgs; [ - nmap - ]; + environment.systemPackages = with pkgs; [ nmap ]; - imports = [ - ../local.nix - ]; + imports = [ ./mail.nix ]; environment = { etc = { diff --git a/config/postgresql_11.nix b/config/postgresql_11.nix deleted file mode 100644 index e2238cb..0000000 --- a/config/postgresql_11.nix +++ /dev/null @@ -1,75 +0,0 @@ -{ config, lib, pkgs, ... }: - -with lib; - -let - - catLines = builtins.concatStringsSep "\n"; - - userOpts = { config, ... }: { - options = { - passwd = mkOption { - type = types.str; - description = '' - The password of a given user. - ''; - }; - - databases = mkOption { - type = types.attrsOf types.lines; - default = {}; - description = '' - A list of databases to which this user should have access. - ''; - }; - }; - }; - - grantDatabaseAccess = username: database: '' - GRANT CONNECT ON DATABASE ${database} TO USER ${username}; - GRANT SELECT,INSERT,UPDATE,DELETE ON ALL TABLES IN SCHEMA ${database} TO USER ${username}; - ''; - - createUserSql = username: userOpts: '' - CREATE ROLE ${username} ENCRYPTED PASSWORD ${userOpts.passwd}; - ${catLines (map (grantDatabaseAccess username) userOpts.databases)} - ''; - - createDatabaseSql = database: dbOpts: '' - CREATE DATABASE ${database}; - USE ${database}; - ''; - - dataPath = /srv + ("/" + config.networking.hostName); - -in { - - options = { - fudo.postgresql = { - - enable = mkOption { - type = types.bool; - default = false; - description = '' - Whether to enable the PostgreSQL server for Fudo services. - ''; - }; - - databases = mkOption { - type = types.attrsOf types.lines; - default = {}; - description = '' - A map of database_name => database_defn. - ''; - }; - - users = mkOption { - type = with types; attrsOf (submodule userOpts); - default = {}; - description = '' - A map of user_name => { user_attributes }. - ''; - }; - }; - }; -} diff --git a/defaults.nix b/defaults.nix index e7821ff..9cb1c34 100644 --- a/defaults.nix +++ b/defaults.nix @@ -2,14 +2,14 @@ { config, pkgs, lib, ... }: -let - state-version = "20.03"; +let state-version = "20.03"; in { imports = [ ./hardware-configuration.nix ./packages/local.nix - ./config/local.nix + ./config + ./bash.nix ]; @@ -87,6 +87,7 @@ in { unzip vim wget + xclip yubikey-manager yubikey-personalization ]; @@ -106,13 +107,9 @@ in { xkbOptions = "ctrl:nocaps"; }; - console = { - useXkbConfig = true; - }; + console = { useXkbConfig = true; }; - i18n = { - defaultLocale = "en_US.UTF-8"; - }; + i18n = { defaultLocale = "en_US.UTF-8"; }; programs = { mosh.enable = true; @@ -134,9 +131,7 @@ in { enableSSHSupport = true; }; - fish = { - enable = true; - }; + fish = { enable = true; }; }; services = { @@ -145,9 +140,7 @@ in { enable = true; }; - cron = { - enable = true; - }; + cron = { enable = true; }; openssh = { enable = true; startWhenNeeded = true; @@ -155,16 +148,12 @@ in { extraConfig = '' GSSAPIAuthentication yes GSSAPICleanupCredentials yes - ''; + ''; }; - pcscd = { - enable = true; - }; + pcscd = { enable = true; }; - udev.packages = with pkgs; [ - yubikey-personalization - ]; + udev.packages = with pkgs; [ yubikey-personalization ]; }; environment.shellInit = '' @@ -191,11 +180,7 @@ in { }; }; - users.groups = { - fudosys = { - gid = 888; - }; - }; + users.groups = { fudosys = { gid = 888; }; }; users.extraUsers = { niten = { @@ -203,11 +188,26 @@ in { uid = 10000; createHome = true; description = "Niten"; - shell = pkgs.fish; - extraGroups = ["wheel" "audio" "video" "disk" "floppy" "lp" "cdrom" "tape" "dialout" "adm" "input" "systemd-journal" "fudosys" "libvirtd"]; + extraGroups = [ + "wheel" + "audio" + "video" + "disk" + "floppy" + "lp" + "cdrom" + "tape" + "dialout" + "adm" + "input" + "systemd-journal" + "fudosys" + "libvirtd" + ]; group = "users"; home = "/home/niten"; - hashedPassword = "$6$a1q2Duoe35hd5$IaZGXPfqyGv9uq5DQm7DZq0vIHsUs39sLktBiBBqMiwl/f/Z4jSvNZLJp9DZJYe5u2qGBYh1ca.jsXvQA8FPZ/"; + hashedPassword = + "$6$a1q2Duoe35hd5$IaZGXPfqyGv9uq5DQm7DZq0vIHsUs39sLktBiBBqMiwl/f/Z4jSvNZLJp9DZJYe5u2qGBYh1ca.jsXvQA8FPZ/"; openssh.authorizedKeys.keys = [ "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDoWkjyeIfgwm0b78weToVYOQSD0RQ0qbNzpsN5NokbIFv2/980kLtnYrQEgIJ/JwMLlT3uJYacbCT5/a6Fb8oLxNpj0AF1EKaWZ3Rrlg72Sq+9SEwJwWWmZizX83sovMwUBMaUp6jWLhAhPpzBW5pfc5YWoc89wxGbELSwzgt5EgHbSJgvDnaHSp3fVaY01wfDXbL/oO160iNe7wv2HLMZu/FkWBkIjz6HmoGJJzYM89bUpHbyYG28lmCHB/8UPog5/BsjOn3/qupgf4zh6mMdMsXLvbR2jVwVjxcEMj9N5nCvc+Y3oi7Mij6VNrWbhkaAJMEzeMhWYrF3/pFQxUqG37aK3d0gw9kp5tMDLIlAPX4y1lfA87pIzoa0+Alql0CJQA1IJvp9SFG7lBmSthWQLmZvwwfoGg/ZjF6rOgsVoZ8TizpQnydWJDr6NboU9LL9Oa64OM5Rs0AU3cR2UbOF4QIcWFJ/7oDe3dOnfZ8QYqx9eXJyxoAUpDanaaTHYBiAKkeOBwQU+MVLKCcONKw9FZclf/1TpDB5b3/JeUFANjHQTv0UXA4YYU7iCx6H7XB4qwwtU9O19CGQYYfCfULX12/fRpYJw6VJaQWyyU4Bn5dk/dcB2nGI36jwbLMfhbUTIApujioAnd/GQIMakHEZ1+syPhMx9BxMkZb99B0A1Q== openpgp:0x4EC95B64" ]; @@ -217,10 +217,26 @@ in { uid = 10049; createHome = true; description = "Reaper"; - extraGroups = ["wheel" "audio" "video" "disk" "floppy" "lp" "cdrom" "tape" "dialout" "adm" "input" "systemd-journal" "fudosys" "libvirtd"]; + extraGroups = [ + "wheel" + "audio" + "video" + "disk" + "floppy" + "lp" + "cdrom" + "tape" + "dialout" + "adm" + "input" + "systemd-journal" + "fudosys" + "libvirtd" + ]; group = "users"; home = "/home/reaper"; - hashedPassword = "$6$YVCI6kiGcG5EVMT$t9lYEXjAhbnh7YkvJJPAbrzL8XE/AASsKFlWWeS.fDjBi/8S7zwXTHF0j41nDUfC//3viysn0tIOQKyZTHhzG."; + hashedPassword = + "$6$YVCI6kiGcG5EVMT$t9lYEXjAhbnh7YkvJJPAbrzL8XE/AASsKFlWWeS.fDjBi/8S7zwXTHF0j41nDUfC//3viysn0tIOQKyZTHhzG."; }; fudo = { isSystemUser = true; diff --git a/fudo/users.nix b/fudo/users.nix index 9ce4ea3..432aabb 100644 --- a/fudo/users.nix +++ b/fudo/users.nix @@ -75,7 +75,8 @@ uid = 10035; group = "selby"; common-name = "Ken Selby"; - hashed-password = "{SSHA}flr48Sao0/fUp8yl9zFpm8ERnI7qYTds"; + hashed-password = "{SSHA}YvtkEpqsReXcMdrzlui/ZmhIUKN42YO1"; + # hashed-password = "{SSHA}flr48Sao0/fUp8yl9zFpm8ERnI7qYTds"; # hashed-password = "{SSHA}X8DxUcwH2Fzel5UKbGVNhC5B2vg0Prsc"; }; @@ -431,4 +432,11 @@ common-name = "Network Info Mailer"; hashed-password = "{SSHA}UQHfW0IzjIbRU6VV+DraxvZFWt0to3oc"; }; + + selby-forum = { + uid = 10114; + group = "selby"; + common-name = "Selby Forum"; + hashed-password = "{SSHA}f7eDNuwFXRhvants5cJJ/FGtkCKheY2Q"; + }; } diff --git a/hosts/france.nix b/hosts/france.nix index 349ed8b..00aba3d 100644 --- a/hosts/france.nix +++ b/hosts/france.nix @@ -43,6 +43,7 @@ in { nix-prefetch-docker powerdns tshark + vanilla-forum ]; fudo.common = { @@ -268,7 +269,7 @@ in { fudo.mail-server = import ../fudo/email.nix { inherit config; } // { enableContainer = true; - debug = false; + debug = true; monitoring = true; hostname = mail-hostname; @@ -577,6 +578,12 @@ in { }; }; + fudo.ipfs = { + enable = true; + users = [ "niten" "reaper" ]; + api-address = "/ip4/${host_ipv4}/tcp/5001"; + }; + ### # Minecraft ### diff --git a/hosts/france/forum-config/config-defaults.php b/hosts/france/forum-config/config-defaults.php new file mode 100644 index 0000000..c078d59 --- /dev/null +++ b/hosts/france/forum-config/config-defaults.php @@ -0,0 +1,180 @@ + false, // PDO::ATTR_PERSISTENT + 1000 => true, // PDO::MYSQL_ATTR_USE_BUFFERED_QUERY (missing in some PHP installations) +]; + +// Use a dirty cache by default. Try Vanilla with memcached! +$Configuration['Cache']['Enabled'] = true; +$Configuration['Cache']['Method'] = 'dirtycache'; +$Configuration['Cache']['Filecache']['Store'] = PATH_CACHE.'/Filecache'; + +// Technical content stuff. +$Configuration['Garden']['ContentType'] = 'text/html'; +$Configuration['Garden']['Locale'] = 'en'; +$Configuration['Garden']['LocaleCodeset'] = 'UTF8'; + +$Configuration['HotReload']['IP'] = '127.0.0.1'; + +$Configuration['ContentSecurityPolicy']['ScriptSrc']['AllowedDomains'] = []; + +// Site specifics. +$Configuration['Garden']['Installed'] = false; // Has Garden been installed yet? This blocks setup when true. +$Configuration['Garden']['Title'] = 'Vanilla'; +$Configuration['Garden']['Domain'] = ''; +$Configuration['Garden']['WebRoot'] = false; // You can set this value if you are using htaccess to direct into the application, but the correct webroot isn't being recognized. +$Configuration['Garden']['StripWebRoot'] = false; +$Configuration['Garden']['AllowSSL'] = true; +$Configuration['Garden']['PrivateCommunity'] = false; +$Configuration['Garden']['Forms']['HoneypotName'] = 'hpt'; + +// Developer stuff. +$Configuration['Garden']['Debug'] = false; +$Configuration['Garden']['Errors']['LogFile'] = ''; +$Configuration['Garden']['FolderBlacklist'] = ['.', '..', '_svn', '.git']; // Folders we should never search for classes. + +// User registration & authentication. +$Configuration['Garden']['Session']['Length'] = '15 minutes'; +$Configuration['Garden']['Cookie']['Salt'] = ''; // We do this during setup, chill. +$Configuration['Garden']['Cookie']['Name'] = 'Vanilla'; +$Configuration['Garden']['Cookie']['Path'] = '/'; +$Configuration['Garden']['Cookie']['Domain'] = ''; +$Configuration['Garden']['Cookie']['HashMethod'] = 'md5'; // md5 or sha1 +$Configuration['Garden']['Authenticator']['DefaultScheme'] = 'password'; // Types include 'Password', 'Handshake', 'Openid' +$Configuration['Garden']['Authenticator']['RegisterUrl'] = '/entry/register?Target=%2$s'; +$Configuration['Garden']['Authenticator']['SignInUrl'] = '/entry/signin?Target=%2$s'; +$Configuration['Garden']['Authenticator']['SignOutUrl'] = '/entry/signout/{Session_TransientKey}?Target=%2$s'; +$Configuration['Garden']['Authenticator']['EnabledSchemes'] = ['password']; +$Configuration['Garden']['Authenticator']['SyncScreen'] = "smart"; +$Configuration['Garden']['Authenticators']['password']['Name'] = "Password"; +$Configuration['Garden']['UserAccount']['AllowEdit'] = true; // Allow users to edit their account information? (SSO requires accounts be edited in external system). +$Configuration['Garden']['Registration']['Method'] = 'Captcha'; // Options are: Basic, Captcha, Approval, Invitation +$Configuration['Garden']['Registration']['InviteExpiration'] = '1 week'; // When invitations expire. This will be plugged into strtotime(). +$Configuration['Garden']['Registration']['InviteRoles'] = 'FALSE'; +$Configuration['Garden']['Registration']['ConfirmEmail'] = false; +$Configuration['Garden']['Registration']['MinPasswordLength'] = 6; +$Configuration['Garden']['Registration']['NameUnique'] = true; +$Configuration['Garden']['TermsOfService'] = '/home/termsofservice'; // The url to the terms of service. +$Configuration['Garden']['Password']['MinLength'] = 6; +$Configuration['Garden']['Roles']['Manage'] = true; // @deprecated + +// Garden security features +$Configuration['Garden']['Security']['Hsts']['IncludeSubDomains'] = false; +$Configuration['Garden']['Security']['Hsts']['Preload'] = false; +$Configuration['Garden']['Security']['Hsts']['MaxAge'] = 604800; + +// Outgoing email. +$Configuration['Garden']['Email']['UseSmtp'] = false; +$Configuration['Garden']['Email']['SmtpHost'] = ''; +$Configuration['Garden']['Email']['SmtpUser'] = ''; +$Configuration['Garden']['Email']['SmtpPassword'] = ''; +$Configuration['Garden']['Email']['SmtpPort'] = '25'; +$Configuration['Garden']['Email']['SmtpSecurity'] = ''; // ssl/tls +$Configuration['Garden']['Email']['MimeType'] = 'text/plain'; +$Configuration['Garden']['Email']['SupportName'] = 'Support'; +$Configuration['Garden']['Email']['SupportAddress'] = ''; + +// Contact with the mothership. +$Configuration['Garden']['UpdateCheckUrl'] = 'https://open.vanillaforums.com/addons/update'; +$Configuration['Garden']['AddonUrl'] = 'https://open.vanillaforums.com/addons'; +$Configuration['Garden']['VanillaUrl'] = 'https://open.vanillaforums.com'; + +// File handling. +$Configuration['Garden']['CanProcessImages'] = false; +$Configuration['Garden']['Upload']['MaxFileSize'] = '50M'; +$Configuration['Garden']['Upload']['AllowedFileExtensions'] = [ + 'txt', 'jpg', 'jpeg', 'gif', 'png', 'bmp', 'tiff', 'ico', 'zip', 'gz', 'tar.gz', 'tgz', 'psd', 'ai', 'pdf', 'doc', 'xls', 'ppt', 'docx', 'xlsx', 'pptx', 'log', 'rar', '7z' +]; +$Configuration['Garden']['Profile']['MaxHeight'] = 560; +$Configuration['Garden']['Profile']['MaxWidth'] = 560; +$Configuration['Garden']['Thumbnail']['Size'] = 200; + +// Appearance. +$Configuration['Garden']['Theme'] = 'keystone'; +$Configuration['Garden']['MobileTheme'] = 'mobile'; +$Configuration['Garden']['Menu']['Sort'] = ['Dashboard', 'Discussions', 'Questions', 'Activity', 'Applicants', 'Conversations', 'User']; +$Configuration['Garden']['ThemeOptions']['Styles']['Key'] = 'Default'; +$Configuration['Garden']['ThemeOptions']['Styles']['Value'] = '%s_default'; + +// Profiles. +$Configuration['Garden']['Profile']['Public']= true; +$Configuration['Garden']['Profile']['ShowAbout'] = true; +$Configuration['Garden']['Profile']['EditPhotos'] = true; // false to disable user photo editing +$Configuration['Garden']['Profile']['EditUsernames'] = false; +$Configuration['Garden']['BannedPhoto'] = 'https://images.v-cdn.net/banned_large.png'; + +// Embedding forum & comments. +$Configuration['Garden']['Embed']['CommentsPerPage'] = 50; +$Configuration['Garden']['Embed']['SortComments'] = 'desc'; +$Configuration['Garden']['Embed']['PageToForum'] = true; +$Configuration['Garden']['SignIn']['Popup'] = true; // Should the sign-in link pop up or go to it's own page? (SSO requires going to it's own external page) + +// User experience & formatting. +$Configuration['Garden']['InputFormatter'] = 'Rich'; // Html, BBCode, Markdown, Text, Rich +$Configuration['Garden']['MobileInputFormatter'] = 'Rich'; +$Configuration['Garden']['Html']['AllowedElements'] = "a, abbr, acronym, address, area, audio, b, bdi, bdo, big, blockquote, br, caption, center, cite, code, col, colgroup, dd, del, details, dfn, div, dl, dt, em, figure, figcaption, font, h1, h2, h3, h4, h5, h6, hgroup, hr, i, img, ins, kbd, li, map, mark, menu, meter, ol, p, pre, q, s, samp, small, span, strike, strong, sub, sup, summary, table, tbody, td, tfoot, th, thead, time, tr, tt, u, ul, var, video, wbr"; +$Configuration['Garden']['Search']['Mode'] = 'boolean'; // matchboolean, match, boolean, like +$Configuration['Garden']['EditContentTimeout'] = 3600; // -1 means no timeout. 0 means immediate timeout. > 0 is in seconds. 60 * 60 = 3600 (aka 1hr) +$Configuration['Garden']['Format']['Mentions'] = true; +$Configuration['Garden']['Format']['Hashtags'] = false; +$Configuration['Garden']['Format']['YouTube'] = true; +$Configuration['Garden']['Format']['Vimeo'] = true; +$Configuration['Garden']['Format']['EmbedSize'] = 'normal'; // tiny/small/normal/big/huge or WIDTHxHEIGHT + +// Default preferences. Setting these to 'false' disables them globally. +$Configuration['Preferences']['Email']['ConversationMessage'] = '1'; +$Configuration['Preferences']['Email']['BookmarkComment'] = '1'; +$Configuration['Preferences']['Email']['ParticipateComment'] = '0'; +$Configuration['Preferences']['Email']['WallComment'] = '0'; +$Configuration['Preferences']['Email']['ActivityComment'] = '0'; +$Configuration['Preferences']['Email']['DiscussionComment'] = '0'; +$Configuration['Preferences']['Email']['Mention'] = '0'; +$Configuration['Preferences']['Popup']['ConversationMessage'] = '1'; +$Configuration['Preferences']['Popup']['BookmarkComment'] = '1'; +$Configuration['Preferences']['Popup']['ParticipateComment'] = '0'; +$Configuration['Preferences']['Popup']['WallComment'] = '1'; +$Configuration['Preferences']['Popup']['ActivityComment'] = '1'; +$Configuration['Preferences']['Popup']['DiscussionComment'] = '1'; +$Configuration['Preferences']['Popup']['Mention'] = '1'; + +// Module visibility and sorting. +$Configuration['Garden']['Modules']['ShowGuestModule'] = true; +$Configuration['Garden']['Modules']['ShowSignedInModule'] = false; +$Configuration['Garden']['Modules']['ShowRecentUserModule'] = false; +$Configuration['Modules']['Dashboard']['Panel'] = ['MeModule', 'UserBoxModule', 'ActivityFilterModule', 'UserPhotoModule', 'ProfileFilterModule', 'SideMenuModule', 'UserInfoModule', 'GuestModule', 'Ads']; +$Configuration['Modules']['Dashboard']['Content'] = ['MessageModule', 'MeModule', 'UserBoxModule', 'ProfileOptionsModule', 'Notices', 'ActivityFilterModule', 'ProfileFilterModule', 'Content', 'Ads']; +$Configuration['Modules']['Vanilla']['Panel'] = ['MeModule', 'UserBoxModule', 'GuestModule', 'NewDiscussionModule', 'DiscussionFilterModule', 'SignedInModule', 'Ads']; +$Configuration['Modules']['Vanilla']['Content'] = ['MessageModule', 'MeModule', 'UserBoxModule', 'NewDiscussionModule', 'ProfileOptionsModule', 'Notices', 'NewConversationModule', 'NewDiscussionModule', 'DiscussionFilterModule', 'CategoryModeratorsModule', 'Content', 'Ads']; +$Configuration['Modules']['Conversations']['Panel'] = ['MeModule', 'UserBoxModule', 'NewConversationModule', 'SignedInModule', 'GuestModule', 'Ads']; +$Configuration['Modules']['Conversations']['Content'] = ['MessageModule', 'MeModule', 'UserBoxModule', 'NewConversationModule', 'Notices', 'Content', 'Ads']; + +// Routes. +$Configuration['Routes']['DefaultController'] = 'discussions'; +$Configuration['Routes']['DefaultForumRoot'] = 'discussions'; +$Configuration['Routes']['Default404'] = ['dashboard/home/filenotfound', 'NotFound']; +$Configuration['Routes']['DefaultPermission'] = ['dashboard/home/unauthorized', 'NotAuthorized']; +$Configuration['Routes']['UpdateMode'] = 'dashboard/home/updatemode'; diff --git a/hosts/france/forum-config/config.php.nix b/hosts/france/forum-config/config.php.nix new file mode 100644 index 0000000..957c3af --- /dev/null +++ b/hosts/france/forum-config/config.php.nix @@ -0,0 +1,104 @@ +{ config }: + +'' + 0 is in seconds. 60 * 60 = 3600 (aka 1hr) + $Configuration["Garden"]["Format"]["Mentions"] = true; + $Configuration["Garden"]["Format"]["Hashtags"] = false; + $Configuration["Garden"]["Format"]["YouTube"] = true; + $Configuration["Garden"]["Format"]["Vimeo"] = true; + $Configuration["Garden"]["Format"]["EmbedSize"] = "normal"; // tiny/small/normal/big/huge or WIDTHxHEIGHT + + // Module visibility and sorting. + $Configuration["Garden"]["Modules"]["ShowGuestModule"] = true; + $Configuration["Garden"]["Modules"]["ShowSignedInModule"] = false; + $Configuration["Garden"]["Modules"]["ShowRecentUserModule"] = false; + $Configuration["Modules"]["Dashboard"]["Panel"] = ["MeModule", "UserBoxModule", "ActivityFilterModule", "UserPhotoModule", "ProfileFilterModule", "SideMenuModule", "UserInfoModule", "GuestModule", "Ads"]; + $Configuration["Modules"]["Dashboard"]["Content"] = ["MessageModule", "MeModule", "UserBoxModule", "ProfileOptionsModule", "Notices", "ActivityFilterModule", "ProfileFilterModule", "Content", "Ads"]; + $Configuration["Modules"]["Vanilla"]["Panel"] = ["MeModule", "UserBoxModule", "GuestModule", "NewDiscussionModule", "DiscussionFilterModule", "SignedInModule", "Ads"]; + $Configuration["Modules"]["Vanilla"]["Content"] = ["MessageModule", "MeModule", "UserBoxModule", "NewDiscussionModule", "ProfileOptionsModule", "Notices", "NewConversationModule", "NewDiscussionModule", "DiscussionFilterModule", "CategoryModeratorsModule", "Content", "Ads"]; + $Configuration["Modules"]["Conversations"]["Panel"] = ["MeModule", "UserBoxModule", "NewConversationModule", "SignedInModule", "GuestModule", "Ads"]; + $Configuration["Modules"]["Conversations"]["Content"] = ["MessageModule", "MeModule", "UserBoxModule", "NewConversationModule", "Notices", "Content", "Ads"]; + + // Routes. + $Configuration["Routes"]["DefaultController"] = "discussions"; + $Configuration["Routes"]["DefaultForumRoot"] = "discussions"; + $Configuration["Routes"]["Default404"] = ["dashboard/home/filenotfound", "NotFound"]; + $Configuration["Routes"]["DefaultPermission"] = ["dashboard/home/unauthorized", "NotAuthorized"]; + $Configuration["Routes"]["UpdateMode"] = "dashboard/home/updatemode"; + + // Cache. + $Configuration['Cache']['Enabled'] = true; + $Configuration['Cache']['Method'] = 'memcached'; + $Configuration['Cache']['Filecache']['Store'] = PATH_CACHE.'/Filecache'; + $Configuration['memcached']['Store'] = '${config.memcached-server}'; +'' diff --git a/hosts/france/forum-config/constants.php b/hosts/france/forum-config/constants.php new file mode 100644 index 0000000..b96801b --- /dev/null +++ b/hosts/france/forum-config/constants.php @@ -0,0 +1,89 @@ + + * @copyright 2009-2019 Vanilla Forums Inc. + * @license GPL-2.0-only + */ + + if (PHP_VERSION_ID < 70100) { + die("Vanilla requires PHP 7.1 or greater."); + } + + // Define the constants we need to get going. + if (!defined("APPLICATION")) { + define("APPLICATION", "Vanilla"); + } + if (!defined("APPLICATION_VERSION")) { + // Rules for the versioning + // {OSS version}-{Cloud release version}-{? SNAPSHOT if it"s a dev build} + define("APPLICATION_VERSION", "3.3"); + } + if (!defined("DS")) { + define("DS", DIRECTORY_SEPARATOR); + } + if (!defined("STATE_ROOT")) { + define("STATE_ROOT", "${state-root}"); + } + if (!defined("PATH_ROOT")) { + define("PATH_ROOT", "${static-root}"); + } + + // Disable Phar stream + stream_wrapper_unregister("phar"); + + /** + * Bootstrap Before + * + * This file gives developers the opportunity to hook into Garden before any + * real work has been done. Nothing has been included yet, aside from this file. + * No Garden features are available yet. + */ + $isWeb = PHP_SAPI !== "cli" && isset($_SERVER["REQUEST_METHOD"]); + if ($isWeb && file_exists(STATE_ROOT."/conf/bootstrap.before.php")) { + require_once STATE_ROOT."/conf/bootstrap.before.php"; + } + + /** + * Define Core Constants + * + * Garden depends on the presence of a certain base set of defines that allow it + * to be aware of its own place within the system. These are conditionally + * defined here, in case they"ve already been set by a zealous bootstrap.before. + */ + + // Path to the primary configuration file. + if (!defined("PATH_CONF")) { + define("PATH_CONF", "${config-root}"); + } + + // Include default constants. + require_once PATH_CONF."/constants.php"; + + // Make sure a default time zone is set. + // Do NOT edit this. See config `Garden.GuestTimeZone`. + date_default_timezone_set("UTC"); + + // Make sure the mb_* functions are utf8. + if (function_exists("mb_internal_encoding")) { + mb_internal_encoding("UTF-8"); + } + + // Include the core autoloader. + if (!include_once PATH_ROOT."/vendor/autoload.php") { + die("Could not find the autoloader. Did you forget to run 'composer install' in ".PATH_ROOT."?\n"); + } + spl_autoload_register([Vanilla\AliasLoader::class, "autoload"]); +'' diff --git a/hosts/france/forum-config/index.php b/hosts/france/forum-config/index.php new file mode 100644 index 0000000..f44e685 --- /dev/null +++ b/hosts/france/forum-config/index.php @@ -0,0 +1,29 @@ +start(); +$dispatcher->dispatch(); diff --git a/hosts/france/forum-config/index.php.nix b/hosts/france/forum-config/index.php.nix new file mode 100644 index 0000000..f018786 --- /dev/null +++ b/hosts/france/forum-config/index.php.nix @@ -0,0 +1,33 @@ +{ environment-file, bootstrap-file, ... }: + +'' + start(); + $dispatcher->dispatch(); +'' diff --git a/hosts/france/selby-forum-discourse-unused.nix b/hosts/france/selby-forum-discourse-unused.nix new file mode 100644 index 0000000..83cde12 --- /dev/null +++ b/hosts/france/selby-forum-discourse-unused.nix @@ -0,0 +1,119 @@ +{ config, lib, pkgs, ... }: + +let + hostname = "forum.test.selby.ca"; + local-port = "3157"; + + postgres-host = "france.fudo.org"; + config-path = "/srv/selby-forum/conf"; + redis-data-path = "/srv/selby-forum/redis-data"; + sidekiq-data-path = "/srv/selby-forum/sidekiq-data"; + discourse-data-path = "/srv/selby-forum/discourse-data"; + postgres-data-path = "/srv/selby-forum/postgres-data"; + + env-file = "/srv/selby-forum/private/env"; + + ensure-dir-and-ownership = ownership: dir: '' + if [ ! -d ${dir} ]; then + mkdir -p ${dir} + fi + + chown -R ${ownership} ${dir} + chmod 700 ${dir} + ''; + +in { + config = { + users.users = { + selby-discourse = { + isSystemUser = true; + # This is stupid: needs to be 1001, see bitnami docs + uid = 1001; + }; + }; + + security.acme.certs.${hostname}.email = "niten@fudo.org"; + + services.nginx = { + enable = true; + + virtualHosts = { + "${hostname}" = { + enableACME = true; + forceSSL = true; + + locations."/" = { + proxyPass = "http://127.0.0.1:${local-port}"; + + extraConfig = '' + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-By $server_addr:$server_port; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + ''; + }; + }; + }; + }; + + docker-containers = let + docker-flags = [ "--network=selby-discourse" "--env-file=${env-file}" ]; + discourse-env = { + DISCOURSE_USERNAME = "admin"; + DISCOURSE_SITENAME = "Selby Forum"; + DISCOURSE_EMAIL = "forum@selby.ca"; + DISCOURSE_HOSTNAME = hostname; + + POSTGRESQL_HOST = "selby-discourse-postgres"; + DISCOURSE_POSTGRESQL_USERNAME = "discourse_selby_forum"; + DISCOURSE_POSTGRESQL_NAME = "discourse_selby_forum"; + # note: passwords are stored in env-file + + REDIS_HOST = "selby-discourse-redis"; + # note: password is store in env-file + }; + + in { + selby-discourse = { + image = "bitnami/discourse:2.6.0"; + ports = [ "127.0.0.1:${local-port}:3000" ]; + # user = toString config.users.users.selby-discourse.uid; + volumes = [ + "${config-path}:/opt/bitnami/discourse/mounted-conf" + "${discourse-data-path}:/bitnami" + ]; + extraDockerOptions = docker-flags; + environment = discourse-env; + }; + + selby-discourse-redis = { + image = "bitnami/redis:6.0"; + user = toString config.users.users.selby-discourse.uid; + volumes = [ "${redis-data-path}:/bitnami/redis/data" ]; + extraDockerOptions = docker-flags; + environment = { }; + }; + + selby-discourse-sidekiq = { + image = "bitnami/discourse:2.6.0"; + # user = toString config.users.users.selby-discourse.uid; + volumes = [ "${sidekiq-data-path}:/bitnami" ]; + cmd = [ "nami" "start" "--foreground" "discourse-sidekiq" ]; + extraDockerOptions = docker-flags; + environment = discourse-env; + }; + + selby-discourse-postgres = { + image = "bitnami/postgresql:13"; + # user = toString config.users.users.selby-discourse.uid; + volumes = [ "${postgres-data-path}:/bitnami/postgresql" ]; + extraDockerOptions = docker-flags; + environment = { + POSTGRESQL_DATABASE = "discourse_selby_forum"; + POSTGRESQL_USERNAME = "discourse_selby_forum"; + }; + }; + }; + }; +} diff --git a/hosts/france/selby-forum.nix b/hosts/france/selby-forum.nix index d747291..d856386 100644 --- a/hosts/france/selby-forum.nix +++ b/hosts/france/selby-forum.nix @@ -2,66 +2,195 @@ let hostname = "forum.test.selby.ca"; - postgres-host = "france.fudo.org"; - config-path = "/srv/selby-forum/conf"; - redis-data-path = "/srv/selby-forum/redis-data"; - sidekiq-data-path = "/srv/selby-forum/sidekiq-data"; - discourse-data-path = "/srv/selby-forum/discourse-data"; + + mariadb-tag = "10"; + mariadb-port = "13306"; + mariadb-data-path = "/srv/selby-forum/mariadb-data"; + mariadb-root-env-file = "/srv/selby-forum/private/mariadb-env"; + mariadb-env-file = "/srv/selby-forum/private/mariadb-root-env"; + mariadb-username = "forum_selby_ca"; + mariadb-database = "forum_selby_ca"; + + mariadb-password-file = "/srv/selby-forum/private/mariadb-user-passwd"; + + smtp-password-file = "srv/selby-forum/private/smtp-passwd"; + + fastcgi-params = "include ${pkgs.nginx}/conf/fastcgi_params"; + + memcached-tag = "1.6-alpine"; + memcached-port = "11219"; + + environment = pkgs.writeTextDir "/environment.php" + (import ./forum-config/environment.php.nix { + static-root = "${pkgs.vanilla-forum}"; + state-root = "/srv/selby-forum/state"; + config-root = "/etc/selby-forum"; + }); + + index = pkgs.writeTextDir "/index.php" (import ./forum-config/index.php.nix { + environment-file = "${environment}/environment.php"; + bootstrap-file = "${pkgs.vanilla-forum}/bootstrap.php"; + }); + + selby-forum-pkg = pkgs.symlinkJoin { + name = "selby-forum"; + paths = [ pkgs.vanilla-forum index ]; + }; in { config = { - users.users = { - selby-discourse = { isSystemUser = true; }; - selby-discourse-redis = { isSystemUser = true; }; - selby-discourse-sidekiq = { isSystemUser = true; }; + environment.etc = { + "selby-forum/config-defaults.php" = { + uid = config.users.users.nginx.uid; + mode = "0600"; + source = ./forum-config/config-defaults.php; + }; + "selby-forum/constants.php" = { + uid = config.users.users.nginx.uid; + mode = "0600"; + source = ./forum-config/constants.php; + }; + "selby-forum/config.php" = { + uid = config.users.users.nginx.uid; + mode = "0600"; + text = import ./forum-config/config.php.nix { + config = { + database-host = "127.0.0.1:${mariadb-port}"; + database-name = mariadb-database; + database-user = mariadb-username; + database-password-file = mariadb-password-file; + site-name = "Selby Forum"; + site-domain = "forum.selby.ca"; + smtp-host = "mail.fudo.org"; + smtp-user = "selby-forum"; + smtp-password-file = smtp-password-file; + memcached-server = "127.0.0.1:${memcached-port}"; + }; + }; + }; }; docker-containers = { - # selby-discourse = { - # image = "bitnami/discourse"; - # ports = [ ]; - # user = toString config.users.users.selby-discourse.uid; - # volumes = [ - # "${config-path}:/opt/bitnami/discourse/mounted-conf" - # "${discourse-data-path}:/bitnami" - # ]; - # extraDockerOptions = [ "--network=selby-discourse" ]; - # environment = { - # DISCOURSE_SITENAME = "Selby Forum"; - # DISCOURSE_EMAIL = "forum@selby.ca"; - # DISCOURSE_HOSTNAME = hostname; - # }; - # }; - - selby-discourse-redis = { - image = "bitnami/redis"; - user = toString config.users.users.selby-discourse-redis.uid; - volumes = [ "${redis-data-path}:/bitnami" ]; - extraDockerOptions = [ "--network=selby-discourse" ]; - environment = { ALLOW_EMPTY_PASSWORD = "yes"; }; + selby-forum-mariadb = { + image = "mariadb:${mariadb-tag}"; + ports = [ "127.0.0.1:${mariadb-port}:3306" ]; + volumes = [ "${mariadb-data-path}:/var/lib/mysql" ]; + environment = { + MYSQL_USER = mariadb-username; + MYSQL_DATABASE = mariadb-database; + }; + extraDockerOptions = [ + "--env-file=${mariadb-root-env-file}" + "--env-file=${mariadb-env-file}" + ]; + }; + selby-forum-memcached = { + image = "memcached:${memcached-tag}"; + ports = [ "127.0.0.1:${memcached-port}:11211" ]; }; - - # selby-discourse-sidekiq = { - # image = "bitnami/discourse"; - # user = toString config.users.users.selby-discourse-sidekiq.uid; - # volumes = [ "${sidekiq-data-path}:/bitnami" ]; - # entrypoint = "nami"; - # cmd = [ "start" "discourse-sidekiq" ]; - # extraDockerOptions = [ "--network=selby-discourse" ]; - # }; }; - systemd = { - services = { - # selby-discourse-config = { - # description = "Generate configuration for Selby discourse server."; - # requiredBy = [ "docker-selby-discourse.service" ]; - # requires = [ "fudo-passwords.target" ]; - # serviceConfig.Type = "oneshot"; - # restartIfChanged = true; + security.acme.certs."${hostname}".email = "niten@fudo.org"; - # script = ""; - # }; + services = { + phpfpm = { + pools.selby-forum = { + user = "nginx"; + group = "nginx"; + + settings = { + "pm" = "dynamic"; + "pm.max_children" = 50; + "pm.start_servers" = 5; + "pm.min_spare_servers" = 1; + "pm.max_spare_servers" = 8; + }; + + phpOptions = '' + memory_limit = 500M + file_uploads = On + allow_url_fopen = On + short_open_tag = On + upload_max_filesize = 100M + max_execution_time = 360 + date.timezone = America/Winnipeg + ''; + }; + }; + + nginx = { + enable = true; + + virtualHosts = { + "${hostname}" = let + forbidden-rxs = [ + "^.htaccess$" + "^/conf/" + "^/cache/" + "^/cgi-bin/" + "^/uploads/imports/" + "^/vendor/" + ]; + + forbidden-rx-entry = entry: + lib.nameValuePair "~* ${entry}" { + return = "403"; + extraConfig = "deny all;"; + }; + + forbidden-rx-entries = + builtins.listToAttrs (map forbidden-rx-entry forbidden-rxs); + + in { + enableACME = true; + forceSSL = true; + + root = "${selby-forum-pkg}/"; + + locations = forbidden-rx-entries // { + "/" = { + index = "index.php"; + tryFiles = "$uri @vanilla"; + }; + + "@vanilla" = { + extraConfig = '' + rewrite ^ /index.php$request_uri last; + ''; + }; + + "~* ^/index.php($|/)" = { + extraConfig = '' + expires -1; + + ${fastcgi-params}; + + fastcgi_split_path_info ^(.+?\.php)(/.*)$; + fastcgi_param SCRIPT_NAME /index.php; + fastcgi_param SCRIPT_FILENAME $realpath_root/index.php; + fastcgi_param X_REWRITE 1; + fastcgi_pass unix:${config.services.phpfpm.pools.selby-forum.socket}; + ''; + }; + }; + }; + }; + }; + }; + + systemd.services = { + phpfpm-selby-forum-socket-perm = { + wantedBy = [ "multi-user.target" "nginx.service" ]; + before = [ "nginx.service" ]; + description = + "Change ownership of the phpfpm socket for selby forum once it's started."; + requires = [ "phpfpm-selby-forum.service" ]; + after = [ "phpfpm.target" "phpfpm-selby-forum.service" ]; + serviceConfig = { + ExecStart = '' + ${pkgs.coreutils}/bin/chown nginx:nginx ${config.services.phpfpm.pools.selby-forum.socket} + ''; + }; }; }; }; diff --git a/hosts/lambda.nix b/hosts/lambda.nix new file mode 100644 index 0000000..7bf9b47 --- /dev/null +++ b/hosts/lambda.nix @@ -0,0 +1,81 @@ +{ lib, config, pkgs, ... }: + +let + hostname = "lambda"; + host-internal-ip = "10.0.0.3"; + host-storage-ip = "10.0.10.1"; + inherit (lib.strings) concatStringsSep; + +in { + + boot.kernelModules = [ "kvm-amd" ]; + + boot.loader.grub.enable = true; + boot.loader.grub.version = 2; + boot.loader.grub.device = "/dev/disk/by-label/nixos-root"; + + hardware.bluetooth.enable = false; + + imports = [ ../defaults.nix ../hardware-configuration.nix ]; + + fudo.common = { + profile = "server"; + site = "seattle"; + }; + + fudo.slynk = { enable = true; }; + + networking = { + hostName = hostname; + + nameservers = [ host-internal-ip ]; + + # Create a bridge for VMs to use + macvlans = { + extif0 = { + interface = "enp3s0f1"; + mode = "bridge"; + }; + storageif0 = { + interface = "enp4s0f1"; + mode = "bridge"; + }; + }; + + interfaces = { + enp3s0f0.useDHCP = false; + enp3s0f1.useDHCP = false; + enp4s0f0.useDHCP = false; + enp4s0f1.useDHCP = false; + + extif0 = { + useDHCP = false; + macAddress = "02:50:f6:52:9f:9d"; + ipv4.addresses = [{ + address = host-internal-ip; + prefixLength = 22; + } + # { + # address = "10.0.10.2"; + # prefixLength = 24; + # } + ]; + }; + + storageif0 = { + useDHCP = false; + macAddress = "02:65:d7:00:7d:1b"; + ipv4.addresses = [{ + address = host-storage-ip; + prefixLength = 24; + }]; + }; + }; + }; + + fudo.ipfs = { + enable = true; + users = [ "niten" ]; + api-address = "/ip4/${host-internal-ip}/tcp/5001"; + }; +} diff --git a/hosts/nostromo.nix b/hosts/nostromo.nix index 657730f..2ed9609 100644 --- a/hosts/nostromo.nix +++ b/hosts/nostromo.nix @@ -24,10 +24,7 @@ in { hardware.bluetooth.enable = false; - imports = [ - ../defaults.nix - ../hardware-configuration.nix - ]; + imports = [ ../defaults.nix ../hardware-configuration.nix ]; fudo.common = { profile = "server"; @@ -74,7 +71,7 @@ in { interface eno2 ia_na 1 ia_pd 2 eno2/0 - ''; + ''; # Create a bridge for VMs to use macvlans = { @@ -93,9 +90,7 @@ in { enp9s0f0.useDHCP = false; enp9s0f1.useDHCP = false; - eno2 = { - useDHCP = true; - }; + eno2 = { useDHCP = true; }; intif0 = { useDHCP = false; @@ -121,19 +116,11 @@ in { }; users = { - users = { - fudo-client = { - isSystemUser = true; - }; - }; + users = { fudo-client = { isSystemUser = true; }; }; groups = { - backplane-powerdns = { - members = [ "backplane-powerdns" ]; - }; - backplane-dns = { - members = [ "backplane-dns" ]; - }; + backplane-powerdns = { members = [ "backplane-powerdns" ]; }; + backplane-dns = { members = [ "backplane-dns" ]; }; }; }; @@ -180,11 +167,7 @@ in { docker-containers = { pihole = { image = "pihole/pihole:4.3.2-1"; - ports = [ - "5353:53/tcp" - "5353:53/udp" - "3080:80/tcp" - ]; + ports = [ "5353:53/tcp" "5353:53/udp" "3080:80/tcp" ]; environment = { ServerIP = host-internal-ip; VIRTUAL_HOST = "dns-hole.sea.fudo.org"; @@ -202,16 +185,19 @@ in { }; }; + fudo.ipfs = { + enable = true; + users = [ "niten" ]; + api-address = "/ip4/${host-internal-ip}/tcp/5001"; + }; + services = { nginx = { enable = true; virtualHosts = { "pihole.sea.fudo.org" = { - serverAliases = [ - "dns-hole.sea.fudo.org" - "hole.sea.fudo.org" - ]; + serverAliases = [ "dns-hole.sea.fudo.org" "hole.sea.fudo.org" ]; locations."/" = { proxyPass = "http://127.0.0.1:3080"; diff --git a/packages/local.nix b/packages/local.nix index 2991642..9bf3af9 100644 --- a/packages/local.nix +++ b/packages/local.nix @@ -16,8 +16,7 @@ in { src = builtins.fetchurl { url = "https://launcher.mojang.com/v1/objects/35139deedbd5182953cf1caa23835da59ca3d7cd/server.jar"; - sha256 = - "01i5nd03sbnffbyni1fa6hsg5yll2h19vfrpcydlivx10gck0ka4"; + sha256 = "01i5nd03sbnffbyni1fa6hsg5yll2h19vfrpcydlivx10gck0ka4"; }; }); @@ -159,8 +158,10 @@ in { doom-emacs-config = pkgs.fetchgit { url = "https://git.fudo.org/niten/doom-emacs.git"; - rev = "467c45705c73ee39acbfabc04c5aaa4099408dc4"; - sha256 = "172ah7ymlwymb4rx719nhsfvsxwmq14nlisba84kw34cmhdcsjh7"; + rev = "bc8224ec110e8a69a40d1521665884c4b14bb2b9"; + sha256 = "09j3sfdcfn0qi34qspvcmm201klai543i21zx8rixx9qcc40xm7q"; }; + + vanilla-forum = import ./vanilla-forum.nix { pkgs = pkgs; }; }; } diff --git a/packages/vanilla-forum.nix b/packages/vanilla-forum.nix new file mode 100644 index 0000000..bcab13c --- /dev/null +++ b/packages/vanilla-forum.nix @@ -0,0 +1,29 @@ +# NOT USED, CAN DELETE + +{ pkgs, ... }: + +let version = "3.3"; + +in pkgs.stdenv.mkDerivation { + pname = "vanilla-forum"; + version = version; + + src = builtins.fetchurl { + name = "vanilla-forum-${version}.zip"; + url = "https://us.v-cdn.net/5018160/uploads/addons/3JQXC5NIGUWR.zip"; + sha256 = "13062ar0mdaaihzj6jx9kjvfvsg3km8khvad1rm9cqxviim9rzv3"; + }; + + nativeBuildInputs = with pkgs; [ unzip ]; + + installPhase = '' + mkdir $out + cp -aR -t $out applications bootstrap.php dist js library locales plugins resources themes uploads vendor + ''; + + meta = { + homepage = "http://vanillaforums.com/"; + description = "Vanilla Web Forum"; + downloadPage = "https://open.vanillaforums.com/download"; + }; +} diff --git a/static/add-fudo-ssh-key.rb b/static/add-fudo-ssh-key.rb new file mode 100755 index 0000000..f48d9b9 --- /dev/null +++ b/static/add-fudo-ssh-key.rb @@ -0,0 +1,48 @@ +#!/usr/bin/env ruby + +require 'uri' +require 'net/http' +require 'net/https' +require 'json' +require 'socket' + +if ! ENV['FUDO_GIT_TOKEN'] + puts "FUDO_GIT_TOKEN must be set first" + exit 1 +end + +token = ENV['FUDO_GIT_TOKEN'] + +if ARGV.length != 1 + puts "usage: #{$0} " + exit 1 +end + +filename = ARGV[0] + +if not File::exist?(filename) + puts "file does not exist: #{filename}" + exit 2 +end + +target_uri = URI.parse("https://git.fudo.org/api/v1/admin/users/fudo/keys") + +key = File::open(filename).read.strip + +hostname = Socket::gethostname + +@payload = { + key: key, + read_only: true, + title: "#{hostname} fudo key" +} + +https = Net::HTTP.new(target_uri.host, target_uri.port) +https.use_ssl = true +req = Net::HTTP::Post.new(target_uri.path, initheader = { + 'Content-Type' => 'application/json', + 'Authorization' => "token #{token}" + }) +req.body = @payload.to_json +res = https.request(req) +puts "response #{res.code} #{res.message}: #{res.body}" diff --git a/static/bash/bash.colors b/static/bash/bash.colors new file mode 100644 index 0000000..bb5a8b0 --- /dev/null +++ b/static/bash/bash.colors @@ -0,0 +1,72 @@ +# Reset +Color_Off='\e[0m' # Text Reset + +# Regular Colors +Black='\e[0;30m' # Black +Red='\e[0;31m' # Red +Green='\e[0;32m' # Green +Yellow='\e[0;33m' # Yellow +Blue='\e[0;34m' # Blue +Purple='\e[0;35m' # Purple +Cyan='\e[0;36m' # Cyan +White='\e[0;37m' # White + +# Bold +BBlack='\e[1;30m' # Black +BRed='\e[1;31m' # Red +BGreen='\e[1;32m' # Green +BYellow='\e[1;33m' # Yellow +BBlue='\e[1;34m' # Blue +BPurple='\e[1;35m' # Purple +BCyan='\e[1;36m' # Cyan +BWhite='\e[1;37m' # White + +# Underline +UBlack='\e[4;30m' # Black +URed='\e[4;31m' # Red +UGreen='\e[4;32m' # Green +UYellow='\e[4;33m' # Yellow +UBlue='\e[4;34m' # Blue +UPurple='\e[4;35m' # Purple +UCyan='\e[4;36m' # Cyan +UWhite='\e[4;37m' # White + +# Background +On_Black='\e[40m' # Black +On_Red='\e[41m' # Red +On_Green='\e[42m' # Green +On_Yellow='\e[43m' # Yellow +On_Blue='\e[44m' # Blue +On_Purple='\e[45m' # Purple +On_Cyan='\e[46m' # Cyan +On_White='\e[47m' # White + +# High Intensity +IBlack='\e[0;90m' # Black +IRed='\e[0;91m' # Red +IGreen='\e[0;92m' # Green +IYellow='\e[0;93m' # Yellow +IBlue='\e[0;94m' # Blue +IPurple='\e[0;95m' # Purple +ICyan='\e[0;96m' # Cyan +IWhite='\e[0;97m' # White + +# Bold High Intensity +BIBlack='\e[1;90m' # Black +BIRed='\e[1;91m' # Red +BIGreen='\e[1;92m' # Green +BIYellow='\e[1;93m' # Yellow +BIBlue='\e[1;94m' # Blue +BIPurple='\e[1;95m' # Purple +BICyan='\e[1;96m' # Cyan +BIWhite='\e[1;97m' # White + +# High Intensity backgrounds +On_IBlack='\e[0;100m' # Black +On_IRed='\e[0;101m' # Red +On_IGreen='\e[0;102m' # Green +On_IYellow='\e[0;103m' # Yellow +On_IBlue='\e[0;104m' # Blue +On_IPurple='\e[0;105m' # Purple +On_ICyan='\e[0;106m' # Cyan +On_IWhite='\e[0;107m' # White diff --git a/static/bash/bash.env b/static/bash/bash.env new file mode 100644 index 0000000..effd95b --- /dev/null +++ b/static/bash/bash.env @@ -0,0 +1,22 @@ + +if [ -d /fudo/etc ]; then + FUDO_CONFIG=/fudo/etc +fi + +if [ -f $HOME/.bash_local ]; then + . $HOME/.bash_local +fi + +if [ -f $HOME/.bash_env ]; then + . $HOME/.bash_env +fi + +if [ -f $HOME/.bash_prompt ]; then + . $HOME/.bash_prompt +elif [ "${TERM}x" == "dumbx" ]; then + export PS1="\u@\h:\w > " +elif [ $( type -t __makePS1 ) ]; then + export PROMPT_COMMAND=__makePS1 +else + export PS1="\u@\h:\w > " +fi diff --git a/static/bash/bash.helpers b/static/bash/bash.helpers new file mode 100644 index 0000000..4f5ab06 --- /dev/null +++ b/static/bash/bash.helpers @@ -0,0 +1,99 @@ +#!/usr/bin/env bash + +function __makeTerminalTitle() { + local title='' + + local CURRENT_DIR="${PWD/#$HOME/\~}" + + if [ -n "${SSH_CONNECTION}" ] || [ $UID -eq 0 ]; then + title+="`hostname`:${CURRENT_DIR} [`whoami`@`hostname -f`]" + else + title+="${CURRENT_DIR} [`whoami`]" + fi + + echo -en '\033]2;'${title}'\007' +} + +function __getMachineId() { + if [ -f /etc/machine-id ]; then + echo $((0x$(cat /etc/machine-id | head -c 15))) + elif [ -x "$(which hostid 2>&1)" ]; then + echo $(( (${#HOSTNAME}+0x$(hostid)))) + else + echo "00000000" + fi +} + +function __makePS1() { + local EXIT="$?" + + if [ ! -n "${HOST_COLOR}" ]; then + local H=$(__getMachineId) + HOST_COLOR=$(tput setaf $((H%5 + 2))) # foreground + fi + + PS1='' + + if [ ${USER} == root ]; then + PS1+="\[${Red}\]" # root + elif [ ${USER} != ${LOGNAME} ]; then + PS1+="\[${Blue}\]" # normal user + else + PS1+="\[${Green}\]" # normal user + fi + PS1+="\u\[${Color_Off}\]" + + if [ -n "${SSH_CONNECTION}" ] || [ $UID -eq 0 ]; then + PS1+="\[${Purple}\]@\[${Color_Off}\]" + PS1+="\[${UWhite}${HOST_COLOR}\]\h\[${Color_Off}\]" # host displayed only if ssh connection + fi + + PS1+="\[${Purple}\]:\w" # working directory + + # screen sessions + local SCREEN_PATHS="/var/run/screens/S-`whoami` /var/run/screen/S-`whoami` /var/run/uscreens/S-`whoami`" + + for screen_path in ${SCREEN_PATHS}; do + if [ -d ${screen_path} ]; then + SCREEN_JOBS=`ls ${screen_path} | wc -w` + if [ ${SCREEN_JOBS} != 0 ]; then + local current_screen="$(echo ${STY} | cut -d '.' -f 1)" + if [ -n "${current_screen}" ]; then + current_screen=":${current_screen}" + fi + PS1+=" \[${BGreen}\][s${SCREEN_JOBS}${current_screen}]\[${Color_Off}\]" + fi + break + fi + done + + # git branch + if [ -x "`which git 2>&1`" ]; then + local branch="$(git name-rev --name-only HEAD 2>/dev/null)" + + if [ -n "${branch}" ]; then + local git_status="$(git status --porcelain -b 2>/dev/null)" + local letters="$( echo "${git_status}" | grep --regexp=' \w ' | sed -e 's/^\s\?\(\w\)\s.*$/\1/' )" + local untracked="$( echo "${git_status}" | grep -F '?? ' | sed -e 's/^\?\(\?\)\s.*$/\1/' )" + local status_line="$( echo -e "${letters}\n${untracked}" | sort | uniq | tr -d '[:space:]' )" + PS1+=" \[${Blue}\](git: ${branch}" + if [ -n "${status_line}" ]; then + PS1+=" ${status_line}" + fi + PS1+=")\[${Color_Off}\]" + fi + fi + + PS1+="\n" + + # exit code + if [ ${EXIT} != 0 ]; then + PS1+="\[${BRed}\][!${EXIT}]\[${Color_Off}\]" + else + PS1+="\[${Green}\][${EXIT}]\[${Color_Off}\]" + fi + + PS1+="\[${Purple}\]->\[${Color_Off}\] " # prompt + + __makeTerminalTitle +} diff --git a/users/niten.nix b/users/niten.nix index 4c37375..43e8a38 100644 --- a/users/niten.nix +++ b/users/niten.nix @@ -6,6 +6,8 @@ let in { programs = { + bash = { enable = true; }; + git = { enable = true; userName = name; @@ -33,20 +35,30 @@ in { # tray = true; # }; - home.file = { - ".doom.d" = { - source = pkgs.doom-emacs-config; - recursive = true; - onChange = "${pkgs.doomEmacsInit}/bin/doom-emacs-init.sh"; + home = { + file = { + ".doom.d" = { + source = pkgs.doom-emacs-config; + recursive = true; + onChange = "${pkgs.doomEmacsInit}/bin/doom-emacs-init.sh"; + }; + + ".k5login" = { + source = pkgs.writeText "niten-k5login" '' + niten@FUDO.ORG + niten/root@FUDO.ORG + niten@INFORMIS.LAND + niten/root@INFORMIS.LAND + ''; + }; }; - ".k5login" = { - source = pkgs.writeText "niten-k5login" '' - niten@FUDO.ORG - niten/root@FUDO.ORG - niten@INFORMIS.LAND - niten/root@INFORMIS.LAND - ''; + sessionVariables = { + EDITOR = "emacsclient -t"; + ALTERNATE_EDITOR = ""; + + # Don't put duplicates or whitespace in bash history + HISTCONTROL = "ignoredups:ignorespace"; }; }; } diff --git a/users/root.nix b/users/root.nix index 4a7c463..c31816f 100644 --- a/users/root.nix +++ b/users/root.nix @@ -15,20 +15,29 @@ in { services.gpg-agent.enable = true; - home.file = { - ".doom.d" = { - source = pkgs.doom-emacs-config; - recursive = true; - onChange = "${pkgs.doomEmacsInit}/bin/doom-emacs-init.sh"; - }; + home = { + file = { + ".doom.d" = { + source = pkgs.doom-emacs-config; + recursive = true; + onChange = "${pkgs.doomEmacsInit}/bin/doom-emacs-init.sh"; + }; - ".k5login" = { - source = pkgs.writeText "niten-k5login" '' + ".k5login" = { + source = pkgs.writeText "niten-k5login" '' niten@FUDO.ORG niten/root@FUDO.ORG niten@INFORMIS.LAND niten/root@INFORMIS.LAND ''; + }; + }; + + sessionVariables = { + EDITOR = "emacsclient -t"; + ALTERNATE_EDITOR = ""; + + HISTCONTROL = "ignoredups:ignorespace"; }; }; }