From aef8039358b3d9f0cbd47dfa04ab3d24a2c05e5c Mon Sep 17 00:00:00 2001 From: Cara Salter Date: Wed, 6 Apr 2022 12:22:54 -0400 Subject: flakes + projects --- flake.lock | 91 ++++++++++++++++++++++++++++++++ flake.nix | 128 +++++++++++++++++++++++++++++++++++++++++++++ projects/site.md | 19 +++++++ src/blog/mod.rs | 2 +- src/internal/mod.rs | 4 +- src/main.rs | 9 ++++ src/projects/mod.rs | 38 ++++++++++++++ templates/bloglist.rs.html | 8 +-- 8 files changed, 293 insertions(+), 6 deletions(-) create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 projects/site.md create mode 100644 src/projects/mod.rs diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..c60e477 --- /dev/null +++ b/flake.lock @@ -0,0 +1,91 @@ +{ + "nodes": { + "flake-utils": { + "locked": { + "lastModified": 1648297722, + "narHash": "sha256-W+qlPsiZd8F3XkzXOzAoR+mpFqzm3ekQkJNa+PIh1BQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "0f8662f1319ad6abf89b3380dd2722369fc51ade", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "mozillapkgs": { + "flake": false, + "locked": { + "lastModified": 1645464064, + "narHash": "sha256-YeN4bpPvHkVOpQzb8APTAfE7/R+MFMwJUMkqmfvytSk=", + "owner": "mozilla", + "repo": "nixpkgs-mozilla", + "rev": "15b7a05f20aab51c4ffbefddb1b448e862dccb7d", + "type": "github" + }, + "original": { + "owner": "mozilla", + "repo": "nixpkgs-mozilla", + "type": "github" + } + }, + "naersk": { + "inputs": { + "nixpkgs": "nixpkgs" + }, + "locked": { + "lastModified": 1648544490, + "narHash": "sha256-EoBDcccV70tfz2LAs5lK0BjC7en5mzUVlgLsd5E6DW4=", + "owner": "nix-community", + "repo": "naersk", + "rev": "e30ef9a5ce9b3de8bb438f15829c50f9525ca730", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "naersk", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1648219316, + "narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "30d3d79b7d3607d56546dd2a6b49e156ba0ec634", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1648219316, + "narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "30d3d79b7d3607d56546dd2a6b49e156ba0ec634", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "type": "indirect" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "mozillapkgs": "mozillapkgs", + "naersk": "naersk", + "nixpkgs": "nixpkgs_2" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..be5a1ef --- /dev/null +++ b/flake.nix @@ -0,0 +1,128 @@ +{ + inputs = { + flake-utils.url = "github:numtide/flake-utils"; + naersk.url = "github:nix-community/naersk"; + mozillapkgs = { + url = "github:mozilla/nixpkgs-mozilla"; + flake = false; + }; + }; + + outputs = { self, nixpkgs, flake-utils, naersk, mozillapkgs }: + flake-utils.lib.eachDefaultSystem ( + system: let + pkgs = nixpkgs.legacyPackages."${system}"; + mozilla = pkgs.callPackage (mozillapkgs + "/package-set.nix") {}; + rust = (mozilla.rustChannelOf { + date = "2022-03-31"; + channel = "nightly"; + sha256 = "k6wD6/2qNQ7rmIvGi1ddtKSTUXjXFbIr0Sg2mqF2nYg="; + }).rust; + + naersk-lib = naersk.lib."${system}".override { + cargo = rust; + rustc = rust; + }; + in + rec { + # `nix build` + packages.carasite = naersk-lib.buildPackage { + pname = "carasite"; + root = ./.; + remapPathPrefix = true; + buildInputs = with pkgs; [ + git + ]; + overrideMain = attrs: { + preBuild = '' + ls -alR src + cp -r templates /build/dummy-src/ + cp -r statics /build/dummy-src/ + ''; + + postInstall = '' + mv $out/bin/site $out/bin/carasite + + cp -rf $src/blog $out/blog + cp -rf $src/statics $out/css + cp -rf $src/projects $out/projects + ''; + + }; + }; + defaultPackage = packages.carasite; + + # `nix run` + apps.carasite = flake-utils.lib.mkApp { + drv = packages.carasite; + }; + defaultApp = apps.carasite; + + nixosModules.site = { config, lib, ... }: { + options = { + cara.services.carasite.enable = lib.mkEnableOption "enable cara's site"; + cara.services.carasite.domain = lib.mkOption { + type = lib.types.str; + default = "devcara.com"; + description = "The domain to use"; + }; + + cara.services.carasite.port = lib.mkOption { + type = lib.types.port; + default = 3000; + description = "The port to bind to"; + }; + }; + + config = lib.mkIf config.cara.services.carasite.enable { + users.users.cara-site = { + createHome = true; + isSystemUser = true; + home = "/var/lib/cara-site"; + group = "cara-site"; + }; + + systemd.services.cara-site = { + wantedBy = [ "multi-user.target" ]; + environment = { + PORT = "${config.cara.services.carasite.port}"; + }; + serviceConfig = { + User = "cara-site"; + Group = "cara-site"; + Restart = "always"; + WorkingDirectory = "/var/lib/cara-site"; + script = let site = defaultPackage; + in '' + export PORT=${config.cara.services.carasite.port} + cd ${site} + exec ${site/bin/xesite} + ''; + }; + }; + + services.nginx = { + enable = true; + recommendedProxySettings = true; + recommendedTlsSettings = true; + virtualHosts."${config.cara.services.carasite.domain}" = { + addSSL = true; + forceSSL = true; + enableACME = true; + + locations."/" = { + proxyPass = "http://127.0.0.1:${config.cara.services.carasite.port}"; + }; + }; + }; + }; + }; + + + # `nix develop` + devShell = pkgs.mkShell { + nativeBuildInputs = with pkgs; [ rustc cargo ]; + }; + } + ); +} diff --git a/projects/site.md b/projects/site.md new file mode 100644 index 0000000..4f6ae85 --- /dev/null +++ b/projects/site.md @@ -0,0 +1,19 @@ +--- +title: Website +date: 2022-03-29 +--- + +# Overview + +This site used to be written using [Hugo][hugo], and written in Markdown. It's now +written in Rust, with content remaining in Markdown. I mostly chose to do this +so I could explore more of frontend development and especially the Rust web +ecosystem. + +[hugo]: https://gohugo.io + +# Architecture + +The Rust backend is hosted at +[muirrum/site](https://git.devcara.com/muirrum/site). It loads the markdown into +HTML and stores it in global state that's then passed to each handler. diff --git a/src/blog/mod.rs b/src/blog/mod.rs index 811de15..ac1413e 100644 --- a/src/blog/mod.rs +++ b/src/blog/mod.rs @@ -14,7 +14,7 @@ pub mod handlers { pub async fn list(state: Arc) -> Result { let state = state.clone(); - Response::builder().html(|o| templates::bloglist_html(o, state.blog.clone())) + Response::builder().html(|o| templates::bloglist_html(o, state.blog.clone(), "Posts".into())) } pub async fn post(name: String, state: Arc) -> Result { diff --git a/src/internal/mod.rs b/src/internal/mod.rs index 2a5fa56..5f42764 100644 --- a/src/internal/mod.rs +++ b/src/internal/mod.rs @@ -5,10 +5,12 @@ pub mod markdown; pub struct SiteState { pub blog: Vec, + pub projects: Vec, } pub async fn init() -> Result { let blog = crate::blog::post::load("blog").await?; + let projects = crate::blog::post::load("projects").await?; - Ok(SiteState { blog }) + Ok(SiteState { blog, projects }) } diff --git a/src/main.rs b/src/main.rs index 21eac18..b4801ad 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,6 +8,7 @@ use warp::{path, Filter}; use std::str::FromStr; pub mod blog; +pub mod projects; mod internal; pub mod misc; @@ -35,9 +36,17 @@ async fn main() -> Result<()> { .and(give_site_state(state.clone())) .and_then(blog::handlers::post); + let project_index = warp::path!("projects") + .and(give_site_state(state.clone())) + .and_then(projects::handlers::list); + let project = warp::path!("projects" / String) + .and(give_site_state(state.clone())) + .and_then(projects::handlers::project); + let static_files = warp::path("static").and(warp::fs::dir("./statics")); let site = index.or(about) .or(blog_index.or(blog_post)) + .or(project_index.or(project)) .or(static_files) .with(warp::log("site")); diff --git a/src/projects/mod.rs b/src/projects/mod.rs new file mode 100644 index 0000000..f69c2c0 --- /dev/null +++ b/src/projects/mod.rs @@ -0,0 +1,38 @@ +use crate::blog::post; +pub mod handlers { + + use color_eyre::eyre::eyre; + use std::sync::Arc; + + use crate::templates::{self, Html, RenderRucte}; + use warp::http::Response; + use warp::{Rejection, Reply}; + + use crate::internal::SiteState; + + use crate::blog::post::Post; + + pub async fn list(state: Arc) -> Result { + let state = state.clone(); + Response::builder().html(|o| templates::bloglist_html(o, state.projects.clone(), "Projects".into())) + } + + pub async fn project(name: String, state: Arc) -> Result { + let mut want: Option = None; + + for post in &state.projects { + if post.link == format!("projects/{}", name) { + want = Some(post.clone()); + break; + } + } + + match want { + Some(post) => { + let body = Html(post.body_html.clone()); + Response::builder().html(|o| templates::post_html(o, post, body)) + } + None => panic!("No post found"), + } + } +} diff --git a/templates/bloglist.rs.html b/templates/bloglist.rs.html index 505f9a7..4621f3f 100644 --- a/templates/bloglist.rs.html +++ b/templates/bloglist.rs.html @@ -1,16 +1,16 @@ @use crate::blog::post::Post; @use super::{header_html, footer_html}; -@(posts: Vec) +@(posts: Vec, kind: String) -@:header_html(Some("Posts"), None) +@:header_html(Some(&kind), None) -

Posts

+

@kind.clone()

-- cgit v1.2.3