@@ -133,8 +133,8 @@ rec {
133133 path = reflex-platform.filterGit ./.;
134134 obelisk = ghcObelisk;
135135 commandWithMigration = ghcObelisk.obelisk-command.overrideAttrs (drv: {
136− postInstall = (drv.postInstall or "") +
137− ''cp -r ${./migration} $out/migration;'';
136+ postInstall = (drv.postInstall or "") +
137+ ''cp -r ${./migration} $out/migration;'';
138138 });
139139 command = pkgs.runCommand commandWithMigration.name { nativeBuildInputs = [pkgs.makeWrapper]; } ''
140140 mkdir -p "$out/bin"
@@ -174,13 +174,80 @@ rec {
174174 '';
175175
176176 compressedJs = frontend: pkgs.runCommand "compressedJs" { buildInputs = [ pkgs.closurecompiler ]; } ''
177− mkdir $out
178− cd $out
179− ln -s "${justStaticExecutables frontend}/bin/frontend.jsexe/all.js" all.unminified.js
180− closure-compiler --externs "${reflex-platform.ghcjsExternsJs}" -O ADVANCED --create_source_map="all.js.map" --source_map_format=V3 --js_output_file="all.js" all.unminified.js
181− echo "//# sourceMappingURL=all.js.map" >> all.js
177+ mkdir $out
178+ cd $out
179+ ln -s "${justStaticExecutables frontend}/bin/frontend.jsexe/all.js" all.unminified.js
180+ closure-compiler --externs "${reflex-platform.ghcjsExternsJs}" -O ADVANCED --create_source_map="all.js.map" --source_map_format=V3 --js_output_file="all.js" all.unminified.js
181+ echo "//# sourceMappingURL=all.js.map" >> all.js
182182 '';
183183
184+ serverModules = {
185+ mkBaseEc2 = { hostName, routeHost, enableHttps, adminEmail, ... }: {...}: {
186+ imports = [
187+ (pkgs.path + /nixos/modules/virtualisation/amazon-image.nix)
188+ ];
189+ networking = {
190+ inherit hostName;
191+ firewall.allowedTCPPorts = if enableHttps then [ 80 443 ] else [ 80 ];
192+ };
193+ security.acme.certs = if enableHttps then {
194+ "${routeHost}".email = adminEmail;
195+ } else {};
196+ ec2.hvm = true;
197+ };
198+
199+ mkObeliskApp =
200+ { exe
201+ , routeHost
202+ , enableHttps
203+ , name ? "backend"
204+ , user ? name
205+ , group ? user
206+ , baseUrl ? "/"
207+ , internalPort ? 8000
208+ , backendArgs ? ""
209+ , ...
210+ }: {...}: {
211+ services.nginx = {
212+ enable = true;
213+ virtualHosts."${routeHost}" = {
214+ enableACME = enableHttps;
215+ forceSSL = enableHttps;
216+ locations.${baseUrl} = {
217+ proxyPass = "http://localhost:" + toString internalPort;
218+ };
219+ };
220+ };
221+ systemd.services.${name} = {
222+ wantedBy = [ "multi-user.target" ];
223+ after = [ "network.target" ];
224+ restartIfChanged = true;
225+ script = ''
226+ ln -sft . '${exe}'/*
227+ mkdir -p log
228+ exec ./backend --port=${toString internalPort} ${backendArgs} >>backend.out 2>>backend.err </dev/null
229+ '';
230+ serviceConfig = {
231+ User = user;
232+ KillMode = "process";
233+ WorkingDirectory = "~";
234+ Restart = "always";
235+ RestartSec = 5;
236+ };
237+ };
238+ users = {
239+ users.${user} = {
240+ description = "${user} service";
241+ home = "/var/lib/${user}";
242+ createHome = true;
243+ isSystemUser = true;
244+ group = group;
245+ };
246+ groups.${group} = {};
247+ };
248+ };
249+ };
250+
184251 serverExe = backend: frontend: assets: config:
185252 pkgs.runCommand "serverExe" {} ''
186253 mkdir $out
@@ -191,58 +258,16 @@ rec {
191258 ln -s ${compressedJs frontend} $out/frontend.jsexe
192259 ''; #TODO: run frontend.jsexe through the asset processing pipeline
193260
194− server = { exe, hostName, adminEmail, routeHost, enableHttps }:
195− let system = "x86_64-linux";
196− nixos = import (pkgs.path + /nixos);
197− backendPort = 8000;
261+ server = { exe, hostName, adminEmail, routeHost, enableHttps }@args:
262+ let
263+ nixos = import (pkgs.path + /nixos);
198264 in nixos {
199− inherit system;
200− configuration = args: {
265+ system = "x86_64-linux";
266+ configuration = {
201267 imports = [
202− (pkgs.path + /nixos/modules/virtualisation/amazon-image.nix)
268+ (serverModules.mkBaseEc2 args)
269+ (serverModules.mkObeliskApp args)
203270 ];
204− networking = {
205− inherit hostName;
206− firewall.allowedTCPPorts = if enableHttps then [ 80 443 ] else [ 80 ];
207− };
208− services.nginx = {
209− enable = true;
210− virtualHosts."${routeHost}" = {
211− enableACME = enableHttps;
212− forceSSL = enableHttps;
213− locations."/" = {
214− proxyPass = "http://localhost:" + toString backendPort;
215− };
216− };
217− };
218− security.acme.certs = if enableHttps then {
219− "${routeHost}".email = adminEmail;
220− } else { };
221− systemd.services.backend = {
222− wantedBy = [ "multi-user.target" ];
223− after = [ "network.target" ];
224− restartIfChanged = true;
225− script = ''
226− ln -sft . "${exe}"/*
227− mkdir -p log
228− exec ./backend >>backend.out 2>>backend.err </dev/null
229− '';
230− serviceConfig = {
231− User = "backend";
232− KillMode = "process";
233− WorkingDirectory = "~";
234− Restart = "always";
235− RestartSec = 5;
236− };
237− };
238− users.extraUsers.backend = {
239− description = "backend service";
240− home = "/var/lib/backend";
241− createHome = true;
242− isSystemUser = true;
243− group = "backend";
244− };
245− ec2.hvm = true;
246271 };
247272 };
248273
@@ -251,6 +276,7 @@ rec {
251276 project = base: projectDefinition:
252277 let assets = processAssets { src = base + "/static"; };
253278 configPath = base + "/config";
279+
254280 projectOut = sys: (getReflexPlatform sys).project (args@{ nixpkgs, ... }:
255281 let mkProject = { android ? null #TODO: Better error when missing
256282 , ios ? null #TODO: Better error when missing
@@ -314,7 +340,7 @@ rec {
314340 inherit linuxExe;
315341 exe = serverOn system;
316342 server = args@{ hostName, adminEmail, routeHost, enableHttps }:
317− server (args // { exe = linuxExe;});
343+ server (args // { exe = linuxExe; });
318344 obelisk = import (base + "/.obelisk/impl") {};
319345 };
320346 haskellPackageSets = {