Merge pull request 'added actions' (#1) from rust-nix-refactor into main
Some checks failed
Build and Test / build (push) Has been cancelled

Reviewed-on: #1
This commit was merged in pull request #1.
This commit is contained in:
2026-01-31 20:50:15 +00:00
9 changed files with 100 additions and 21 deletions

25
.gitea/workflows/ci.yaml Normal file
View File

@@ -0,0 +1,25 @@
name: Build and Test
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: production-runner
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Kill existing process
run: |
pkill site || true
- name: Build
run: cargo build --release
- name: Start Application
run: |
nohup ./target/release/site > server.log 2>&1 &

View File

@@ -14,31 +14,38 @@ fn load_posts() -> Result<HashMap<String, Post>, Error> {
let dirs = fs::read_dir("static/posts")?;
let re_title = Regex::new(r#"#let\s+post_title\s*=\s*"([^"]*)""#).unwrap();
let re_slug = Regex::new(r#"#let\s+post_slug\s*=\s*"([^"]*)""#).unwrap();
let re_summary = Regex::new(r#"#let\s+post_summary\s*=\s*"([^"]*)""#).unwrap();
let re_img = Regex::new(r#"#let\s+post_preview_image\s*=\s*"([^"]*)""#).unwrap();
let re_title = Regex::new("(?m)^=+ (.*)").unwrap();
let mut posts: HashMap<String, Post> = HashMap::new();
for dir in dirs {
let typst_path = dir.as_ref().unwrap().path().join("post.typ");
let dir_path = dir.as_ref().unwrap().path();
let typst_path = dir_path.join("post.typ");
let typst = fs::read_to_string(typst_path).expect("Failed reading post");
let title = re_title.captures(&typst)
.expect("Post title not found")
.expect(format!("Post title not found in {}", dir_path.to_str().unwrap()).as_str())
.get(1).unwrap().as_str().trim().to_string() ;
println!("{}", title);
let slug = re_slug.captures(&typst)
.expect("Post slug not found")
.get(1).unwrap().as_str().trim().to_string();
let summary = re_summary.captures(&typst)
.expect("Post summary not found")
.get(1).unwrap().as_str().trim().to_string();
let img = dir?.path().join(
let img_path = dir?.path().join(
re_img.captures(&typst)
.expect("Post preview image not found")
.get(1).unwrap().as_str().trim().to_string());
let slug = title.clone().replace(" ", "-").to_lowercase();
.get(1).unwrap().as_str().trim().to_string()
).to_str().expect("Failed converting path to string").to_string();
posts.insert(
slug.clone(),
Post {
title: title.clone(),
slug: slug,
preview_image: img.to_str().expect("Failed converting path to string").to_string(),
title: title,
preview_image: img_path,
summary: summary,
render: Html(PostTemplate {
content: typst_to_html(typst),
@@ -128,7 +135,7 @@ async fn main() {
let site: Router = Router::new()
.route("/", get(home_html))
.route("/posts", get(posts_html))
.route("/posts/{title}", get(|title| get_post(title, posts)))
.route("/posts/{slug}", get(|slug| get_post(slug, posts)))
.nest_service("/static", ServeDir::new("static"));
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();

View File

@@ -1,4 +1,4 @@
#let post_title = "Building a drone"
#let post_slug = "building-a-drone"
#let post_preview_image = "top.jpg"
#let post_summary = "Using a raspberry pi and 3d printer to build a drone from scratch"

View File

@@ -1,4 +1,4 @@
#let post_title = "Game Dev"
#let post_slug = "gamedev"
#let post_preview_image = "flying.webp"
#let post_summary = "Creating an open world multiplayer terrain destruction game in Godot and Rust"

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generator: Adobe Illustrator 26.5.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:cc="http://creativecommons.org/ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Layer_1" inkscape:export-xdpi="299.75104" x="0px" y="0px" viewBox="0 0 127.6 62.9" style="enable-background:new 0 0 127.6 62.9;" xml:space="preserve">
<style type="text/css">
.st0{fill:#0082C9;}
</style>
<path id="path1052" inkscape:connector-curvature="0" inkscape:export-filename="Nextcloud Hub logo variants.png" inkscape:export-xdpi="300" inkscape:export-ydpi="300" class="st0" d=" M63.8,3.8c-12.6,0-23.3,8.5-26.6,20.1c-2.8-6.1-9-10.4-16.2-10.4c-9.9,0-18,8.1-18,18s8.1,18,18,18c7.2,0,13.4-4.3,16.3-10.4 c3.3,11.6,14,20.1,26.6,20.1c12.5,0,23.1-8.4,26.5-19.8c2.9,6,9.1,10.2,16.2,10.2c9.9,0,18-8.1,18-18s-8.1-18-18-18 c-7.1,0-13.2,4.2-16.2,10.2C87,12.2,76.3,3.8,63.8,3.8z M63.8,14.4c9.5,0,17.1,7.6,17.1,17.1s-7.6,17.1-17.1,17.1S46.7,41,46.7,31.5 C46.7,21.9,54.3,14.4,63.8,14.4z M21,24c4.2,0,7.4,3.3,7.4,7.4c0,4.2-3.3,7.4-7.4,7.4c-4.2,0-7.4-3.3-7.4-7.4 C13.6,27.3,16.8,24,21,24z M106.5,24c4.2,0,7.4,3.3,7.4,7.4c0,4.2-3.3,7.4-7.4,7.4c-4.2,0-7.4-3.3-7.4-7.4S102.3,24,106.5,24z"></path>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -0,0 +1,35 @@
#let post_slug = "selfhosting-nextcloud"
#let post_preview_image = "logo.svg"
#let post_summary = "Why and how I host a fileserver locally, on an old laptop"
= Selfhosting Nextcloud
Access it #link("nextcloud.jeremyjanella.com")[here]. Obviously you'd need a username and password first, good luck getting that!
=== Why I selfhost Nextcloud
I'm a constantly-commuting university student. I primarily work on my desktop, take notes and attend lectures and events with my laptop, and review, access, and share documents from my phone. I need the same files to be accessible on all devices at all times.
Nextcloud is a self-hosted, batteries included file server primarily. It also has a working office suite for editing documents on the cloud through your browser, and numerous other extensions.
Mega, Google Drive, and OneDrive all do this. Why would I bother using nextcloud? Isn't that reinventing the wheel? Yes and no.
===== Do tech giants respect privacy? Nextcloud does.
With remotely managed cloud providers, you're trusting large corporations not to look at your data. You are, for free, letting profit-driven entities, to store your data. Of course they could claim to be implementing end-to-end encryption, or that the free tier is a trail of their paid subscription services. As far as I know none of this is open source either, so you're just trusting big-data to hold your data for free without looking at your data. I just don't trust them not to look at my assignments I guess.
I'm not a fan of subscription services. If I can at moderate difficulty not depend on a corporation to keep their subscription prices sane, I will. I'm not sure how much I save by selfhosting nextcloud, but I also have the piece of mind that that price will never change (excluding buying additional drives or electricity price fluctuations).
=== How I selfhost Nextcloud
===== Network and server configurations
I already had an old laptop kicking around, a domain name, and reverse proxy on a static IP. A domain name isn't even really nessecary, unless you want a polished experience.
My laptop already runs linux with docker installed, which would only take a few hours to set up otherwise.
From there I used docker compose to start the #link("https://github.com/nextcloud/all-in-one")[nextcloud all in one].
On my reverse proxy I pointed the `nextcloud` subnet at my home IP in its Caddy file. Caddy is a lot like NGINX except its easier to set up for my use case. My IP doesn't change enough to warrent setting up DDNS, however thats always an option. After the ports are opened the hard part is opening the firewall. The reason this is hard is because I always forget the firewall and spend a solid chunk of time debugging why nothing works. In the end, if nothing is working, tools like `traceroute`, `dig` and `ping` are varying degrees of useful for testing accessibility.
===== Can I get five nines?
No. 99.999% uptime won't happen. Power and network outages happen. Roommates unplug your server or brick the router or close your network ports. The thing is that when these things happen, I still have my files on any device. They just stop syncing temporarily, to resume and correct conflicts when the network is back up.
With recent cloud outages in mind, I want it to be my own fault if I can't access my files. If tech giants side against Canada in some idiocratic war, I don't want to lose data. I don't care enough to implement RAID (yet), but if the server dies or the drive does get corrupted, I can reach into my server drawr, take out the drive, and load up ddrescue on my desktop. Also, the files are already syncing to atleast 3 other devices, data loss doesn't scare me. (Knocks on wood)

View File

@@ -1,4 +1,4 @@
#let post_title = "Phobos"
#let post_slug = "assembly-game"
#let post_preview_image = "phobos.png"
#let post_summary = "Making a rocket platformer in assembly"

View File

@@ -19,7 +19,7 @@
border-radius: 32px;
padding: 10px 20px;
margin: 0 auto;
width: 95%;
width: 85%;
justify-content: space-between;
align-items: center;
@@ -47,7 +47,6 @@
img {
width: 100%;
max-height: 400px;
object-fit: cover;
}
@@ -55,12 +54,11 @@ img {
border: 1px solid whitesmoke;
border-radius: 32px;
margin: auto;
margin-top: 1rem;
margin-bottom: 1rem;
padding-bottom: 1rem;
background-color: linear-gradient(150deg, #222, #040404);
text-align: center;
break-inside: avoid;
}
.postpreview:hover {
@@ -104,9 +102,15 @@ a {
transform: scaleX(1);
}
.menu {
column-width: 300px;
column-gap: 20px;
column-gap: 1rem;
}
.content {
width: 80%;
margin: auto;
width: 90%;
display: inline-block;
}
.content p {

View File

@@ -3,7 +3,7 @@
{% block body %}
<div class="content">
<div class="content menu">
{% for post in posts %}
{% include "post-preview.html" %}
{% endfor %}