feat: ghost
This commit is contained in:
		
							parent
							
								
									a37a72e81f
								
							
						
					
					
						commit
						091b653c9a
					
				
							
								
								
									
										18
									
								
								hosts/profiles/ghost/default.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								hosts/profiles/ghost/default.nix
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,18 @@ | ||||||
|  | {pkgs, ... }: | ||||||
|  | { | ||||||
|  |   services.nginx = { | ||||||
|  |     enable = true; | ||||||
|  |     recommendedGzipSettings = true; | ||||||
|  |     recommendedOptimisation = true; | ||||||
|  |     recommendedProxySettings = true; | ||||||
|  |     recommendedTlsSettings = true; | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   # Enables MySQL | ||||||
|  |   services.mysql = { | ||||||
|  |     enable = true; | ||||||
|  |     package = pkgs.mariadb; | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   services."write.sealight.xyz".enable = true; | ||||||
|  | } | ||||||
							
								
								
									
										148
									
								
								modules/nixos/ghost.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								modules/nixos/ghost.nix
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,148 @@ | ||||||
|  | { options, lib, config, pkgs, ... }: | ||||||
|  | let | ||||||
|  |   # domain for the Ghost blog | ||||||
|  |   serverName = "write.sealight.xyz"; | ||||||
|  |   # port on which the Ghost service runs | ||||||
|  |   port = 1357; | ||||||
|  |   # user used to run the Ghost service | ||||||
|  |   userName = builtins.replaceStrings [ "." ] [ "_" ] serverName; | ||||||
|  |   # MySQL database used by Ghost | ||||||
|  |   dbName = userName; | ||||||
|  |   # MySQL user used by Ghost | ||||||
|  |   dbUser = userName; | ||||||
|  |   # directory used to save the blog content | ||||||
|  |   dataDir = "/var/lib/${userName}"; | ||||||
|  |   # Ghost package we created in the section above | ||||||
|  |   ghost = import ./ghost { inherit pkgs; }; | ||||||
|  |   # script that sets up the Ghost content directory | ||||||
|  |   setupScript = pkgs.writeScript "${serverName}-setup.sh" '' | ||||||
|  |     #! ${pkgs.stdenv.shell} -e | ||||||
|  |     chmod g+s "${dataDir}" | ||||||
|  |     [[ ! -d "${dataDir}/content" ]] && cp -r "${ghost}/content" "${dataDir}/content" | ||||||
|  |     chown -R "${userName}":"${userName}" "${dataDir}/content" | ||||||
|  |     chmod -R +w "${dataDir}/content" | ||||||
|  |     ln -f -s "/etc/${serverName}.json" "${dataDir}/config.production.json" | ||||||
|  |     [[ -d "${dataDir}/current" ]] && rm "${dataDir}/current" | ||||||
|  |     ln -f -s "${ghost}/current" "${dataDir}/current" | ||||||
|  |     [[ -d "${dataDir}/content/themes/casper" ]] && rm "${dataDir}/content/themes/casper" | ||||||
|  |     ln -f -s "${ghost}/current/content/themes/casper" "${dataDir}/content/themes/casper" | ||||||
|  |   ''; | ||||||
|  | 
 | ||||||
|  |   databaseService = "mysql.service"; | ||||||
|  | 
 | ||||||
|  |   serviceConfig = config.services."${serverName}"; | ||||||
|  |   options = { enable = lib.mkEnableOption "${serverName} service"; }; | ||||||
|  | in { | ||||||
|  |   options.services.${serverName} = options; | ||||||
|  |   config = lib.mkIf serviceConfig.enable { | ||||||
|  |     # Creates the user and group | ||||||
|  |     users.users.${userName} = { | ||||||
|  |       isSystemUser = true; | ||||||
|  |       group = userName; | ||||||
|  |       createHome = true; | ||||||
|  |       home = dataDir; | ||||||
|  |     }; | ||||||
|  |     users.groups.${userName} = { }; | ||||||
|  | 
 | ||||||
|  |     # Creates the Ghost config | ||||||
|  |     environment.etc."${serverName}.json".text = '' | ||||||
|  |       { | ||||||
|  |         "url": "https://${serverName}", | ||||||
|  |         "server": { | ||||||
|  |           "port": ${port}, | ||||||
|  |           "host": "0.0.0.0" | ||||||
|  |         }, | ||||||
|  |         "database": { | ||||||
|  |           "client": "mysql", | ||||||
|  |           "connection": { | ||||||
|  |             "host": "localhost", | ||||||
|  |             "user": "${dbUser}", | ||||||
|  |             "database": "${dbName}", | ||||||
|  |             "password": "", | ||||||
|  |             "socketPath": "/run/mysqld/mysqld.sock" | ||||||
|  |           } | ||||||
|  |         }, | ||||||
|  |         "mail": { | ||||||
|  |           "transport": "sendmail" | ||||||
|  |         }, | ||||||
|  |         "logging": { | ||||||
|  |           "transports": ["stdout"] | ||||||
|  |         }, | ||||||
|  |         "paths": { | ||||||
|  |           "contentPath": "${dataDir}/content" | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     ''; | ||||||
|  | 
 | ||||||
|  |     # Sets up the Systemd service | ||||||
|  |     systemd.services."${serverName}" = { | ||||||
|  |       enable = true; | ||||||
|  |       description = "${serverName} ghost blog"; | ||||||
|  |       restartIfChanged = true; | ||||||
|  |       restartTriggers = | ||||||
|  |         [ ghost config.environment.etc."${serverName}.json".source ]; | ||||||
|  |       requires = [ databaseService ]; | ||||||
|  |       after = [ databaseService ]; | ||||||
|  |       path = [ pkgs.nodejs pkgs.vips ]; | ||||||
|  |       wantedBy = [ "multi-user.target" ]; | ||||||
|  |       serviceConfig = { | ||||||
|  |         User = userName; | ||||||
|  |         Group = userName; | ||||||
|  |         WorkingDirectory = dataDir; | ||||||
|  |         # Executes the setup script before start | ||||||
|  |         ExecStartPre = setupScript; | ||||||
|  |         # Runs Ghost with node | ||||||
|  |         ExecStart = "${pkgs.nodejs}/bin/node current/index.js"; | ||||||
|  |         # Sandboxes the Systemd service | ||||||
|  |         AmbientCapabilities = [ ]; | ||||||
|  |         CapabilityBoundingSet = [ ]; | ||||||
|  |         KeyringMode = "private"; | ||||||
|  |         LockPersonality = true; | ||||||
|  |         NoNewPrivileges = true; | ||||||
|  |         PrivateDevices = true; | ||||||
|  |         PrivateMounts = true; | ||||||
|  |         PrivateTmp = true; | ||||||
|  |         ProtectClock = true; | ||||||
|  |         ProtectControlGroups = true; | ||||||
|  |         ProtectHome = true; | ||||||
|  |         ProtectHostname = true; | ||||||
|  |         ProtectKernelLogs = true; | ||||||
|  |         ProtectKernelModules = true; | ||||||
|  |         ProtectKernelTunables = true; | ||||||
|  |         ProtectSystem = "full"; | ||||||
|  |         RemoveIPC = true; | ||||||
|  |         RestrictAddressFamilies = [ ]; | ||||||
|  |         RestrictNamespaces = true; | ||||||
|  |         RestrictRealtime = true; | ||||||
|  |       }; | ||||||
|  |       environment = { NODE_ENV = "production"; }; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     # Sets up the blog virtual host on NGINX | ||||||
|  |     services.nginx.virtualHosts.${serverName} = { | ||||||
|  |       # Sets up Lets Encrypt SSL certificates for the blog | ||||||
|  |       forceSSL = true; | ||||||
|  |       enableACME = true; | ||||||
|  |       locations."/" = { proxyPass = "http://127.0.0.1:${toString port}"; }; | ||||||
|  |       extraConfig = '' | ||||||
|  |         charset UTF-8; | ||||||
|  | 
 | ||||||
|  |         add_header Strict-Transport-Security "max-age=2592000; includeSubDomains" always; | ||||||
|  |         add_header Referrer-Policy "strict-origin-when-cross-origin"; | ||||||
|  |         add_header X-Frame-Options "SAMEORIGIN"; | ||||||
|  |         add_header X-XSS-Protection "1; mode=block"; | ||||||
|  |         add_header X-Content-Type-Options nosniff; | ||||||
|  |       ''; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     # Sets up MySQL database and user for Ghost | ||||||
|  |     services.mysql = { | ||||||
|  |       ensureDatabases = [ dbName ]; | ||||||
|  |       ensureUsers = [{ | ||||||
|  |         name = dbUser; | ||||||
|  |         ensurePermissions = { "${dbName}.*" = "ALL PRIVILEGES"; }; | ||||||
|  |       }]; | ||||||
|  |     }; | ||||||
|  |   }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
							
								
								
									
										9
									
								
								pkgs/ghost/builder.sh
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								pkgs/ghost/builder.sh
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,9 @@ | ||||||
|  | source "$stdenv"/setup | ||||||
|  | 
 | ||||||
|  | export HOME=$(mktemp -d) | ||||||
|  | npm install --loglevel=info --logs-max=0 "ghost-cli@$ghostCliVersion" | ||||||
|  | 
 | ||||||
|  | mkdir --parents "$out"/ | ||||||
|  | node_modules/ghost-cli/bin/ghost install "$version" --db=sqlite3 \ | ||||||
|  |   --no-enable --no-prompt --no-stack --no-setup --no-start --dir "$out" | ||||||
|  | 
 | ||||||
							
								
								
									
										11
									
								
								pkgs/ghost/default.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								pkgs/ghost/default.nix
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | ||||||
|  | { pkgs }: | ||||||
|  | 
 | ||||||
|  | let | ||||||
|  |   pname = "ghost"; | ||||||
|  |   version = "5.8.0"; | ||||||
|  | in pkgs.stdenv.mkDerivation { | ||||||
|  |   inherit pname version; | ||||||
|  |   buildInputs = with pkgs; [ nodejs yarn vips ]; | ||||||
|  |   ghostCliVersion = "1.21.1"; | ||||||
|  |   builder = ./builder.sh; | ||||||
|  | } | ||||||
		Loading…
	
		Reference in a new issue