forked from cadey/xesite
Compare commits
1 Commits
main
...
nix-flakes
Author | SHA1 | Date |
---|---|---|
Cadey Ratio | 2fa5b904a0 |
|
@ -6,5 +6,3 @@ cw.tar
|
||||||
/result
|
/result
|
||||||
.#*
|
.#*
|
||||||
/target
|
/target
|
||||||
.patreon.json
|
|
||||||
.direnv
|
|
||||||
|
|
|
@ -130,9 +130,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "axum"
|
name = "axum"
|
||||||
version = "0.5.0"
|
version = "0.4.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5611d4977882c5af1c0f7a34d51b5d87f784f86912bb543986b014ea4995ef93"
|
checksum = "c9f346c92c1e9a71d14fe4aaf7c2a5d9932cc4e5e48d8fb6641524416eb79ddd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"axum-core",
|
"axum-core",
|
||||||
|
@ -142,7 +142,6 @@ dependencies = [
|
||||||
"http",
|
"http",
|
||||||
"http-body",
|
"http-body",
|
||||||
"hyper",
|
"hyper",
|
||||||
"itoa",
|
|
||||||
"matchit",
|
"matchit",
|
||||||
"memchr",
|
"memchr",
|
||||||
"mime",
|
"mime",
|
||||||
|
@ -161,9 +160,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "axum-core"
|
name = "axum-core"
|
||||||
version = "0.2.0"
|
version = "0.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "95cd109b3e93c9541dcce5b0219dcf89169dcc58c1bebed65082808324258afb"
|
checksum = "6dbcda393bef9c87572779cb8ef916f12d77750b27535dd6819fa86591627a51"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"bytes",
|
"bytes",
|
||||||
|
@ -175,9 +174,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "axum-extra"
|
name = "axum-extra"
|
||||||
version = "0.2.0"
|
version = "0.1.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ff3819ded1be91d7ee2cd9f0466aa345cc70ba0b0035ed47e3eac6427f83b81a"
|
checksum = "b5b6d79bc9c2975821d39c7df31ea766026beb9efe28c076a48cfd7d50f34f18"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"axum",
|
"axum",
|
||||||
"bytes",
|
"bytes",
|
||||||
|
@ -192,9 +191,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "axum-macros"
|
name = "axum-macros"
|
||||||
version = "0.2.0"
|
version = "0.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "63bcb0d395bc5dd286e61aada9fc48201eb70e232f006f9d6c330c9db2f256f5"
|
checksum = "c5b2a9133b2658e684c8ea04157a8bd48dac7906a2eb884ffebfb051af123394"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck",
|
"heck",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
|
@ -1191,9 +1190,9 @@ checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "matchit"
|
name = "matchit"
|
||||||
version = "0.5.0"
|
version = "0.4.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "73cbba799671b762df5a175adf59ce145165747bb891505c43d09aefbbf38beb"
|
checksum = "9376a4f0340565ad675d11fc1419227faf5f60cd7ac9cb2e7185a471f30af833"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "md5"
|
name = "md5"
|
||||||
|
@ -1515,7 +1514,6 @@ dependencies = [
|
||||||
"tokio",
|
"tokio",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-futures",
|
"tracing-futures",
|
||||||
"url",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2469,9 +2467,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing-subscriber"
|
name = "tracing-subscriber"
|
||||||
version = "0.3.11"
|
version = "0.3.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4bc28f93baff38037f64e6f43d34cfa1605f27a49c34e8a04c5e78b0babf2596"
|
checksum = "9e0ab7bdc962035a87fba73f3acca9b8a8d0034c2e6f60b84aeaaddddc155dce"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi_term",
|
"ansi_term",
|
||||||
"sharded-slab",
|
"sharded-slab",
|
||||||
|
|
|
@ -9,9 +9,9 @@ repository = "https://github.com/Xe/site"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
axum = "0.5"
|
axum = "0.4"
|
||||||
axum-macros = "0.2"
|
axum-macros = "0.1"
|
||||||
axum-extra = "0.2"
|
axum-extra = "0.1"
|
||||||
color-eyre = "0.6"
|
color-eyre = "0.6"
|
||||||
chrono = "0.4"
|
chrono = "0.4"
|
||||||
comrak = "0.12.1"
|
comrak = "0.12.1"
|
||||||
|
|
|
@ -1,93 +0,0 @@
|
||||||
---
|
|
||||||
title: Compiling Code to Matter in My Living Room
|
|
||||||
date: 2022-03-28
|
|
||||||
tags:
|
|
||||||
- openscad
|
|
||||||
- 3dprinting
|
|
||||||
---
|
|
||||||
|
|
||||||
In a moment of weakness, my husband and I got a 3d printer. It's mostly been sitting around and not doing much since we got it, but recently I found a great use for it: I wanted a controller stand for my Valve Index controllers and VR full body trackers.
|
|
||||||
|
|
||||||
After doing some digging on Thingiverse, I found [this stand](https://www.thingiverse.com/thing:4587097) that looked like it had promise. So I downloaded the model, sliced it and then sent it over to Kyubey:
|
|
||||||
|
|
||||||
<blockquote class="twitter-tweet"><p lang="tl" dir="ltr">Kyuubey is happy <a href="https://t.co/atTLN8MSgc">pic.twitter.com/atTLN8MSgc</a></p>— Xe Iaso (@theprincessxena) <a href="https://twitter.com/theprincessxena/status/1507485129907871747?ref_src=twsrc%5Etfw">March 25, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
|
|
||||||
|
|
||||||
[Kyubey's name is a reference to <a href="https://madoka.fandom.com/wiki/Kyubey">Kyubey</a> from Puella Magi Madoka Magika</a>.](conversation://Mara/hacker)
|
|
||||||
|
|
||||||
Once it was done I ended up with a stand that I could feed [these cables I got from Amazon](https://www.amazon.ca/gp/product/B09LSF8XL9/) through. The tracker holes worked great, but the controller holes were just barely too small.
|
|
||||||
|
|
||||||
This was kinda frustrating and I almost gave up on the project, but then I remembered that [OpenSCAD](https://openscad.org) existed. OpenSCAD is a weird programming environment / 3D modeling hybrid program that I've seen used on Thingiverse. It works by letting you position platonic solids into a 3d environment, and from there you can create anything you want.
|
|
||||||
|
|
||||||
One of the primitives that OpenSCAD offers is a cylinder. So I wondered if I could use one of those to widen the hole in the index stand and then reprint the part with the wider hole.
|
|
||||||
|
|
||||||
[Wait, you're using a CAD program to fix your 3D print by modifying the model instead of using, I don't know, a drill and 5 minutes to make it fit that way?](conversation://Numa/dismay)
|
|
||||||
|
|
||||||
[There's no doing like overdoing!](conversation://Cadey/enby)
|
|
||||||
|
|
||||||
After some finangling, I managed to get the cylinders in the right place with this OpenSCAD code:
|
|
||||||
|
|
||||||
```scad
|
|
||||||
//difference() {
|
|
||||||
color("magenta") translate([0, 0, 0]) import("./assets/ValveTrackerDeckEditedByInugoro.stl");
|
|
||||||
// bores for controller holders
|
|
||||||
color([0, 1, 0]) translate([63, 44, 0]) cylinder(h = 55, r = 4.75);
|
|
||||||
color([0, 1, 0]) translate([-63, 44, 0]) cylinder(h = 55, r = 4.75);
|
|
||||||
//}
|
|
||||||
```
|
|
||||||
|
|
||||||
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Some finagling required <a href="https://t.co/7T0R6x1XoP">pic.twitter.com/7T0R6x1XoP</a></p>— Xe Iaso (@theprincessxena) <a href="https://twitter.com/theprincessxena/status/1508566854926745614?ref_src=twsrc%5Etfw">March 28, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
|
|
||||||
|
|
||||||
And when I uncommented out the `difference()` block, it ends up looking good enough:
|
|
||||||
|
|
||||||
<blockquote class="twitter-tweet" data-conversation="none" data-dnt="true"><p lang="und" dir="ltr"><a href="https://t.co/fiShvlN8QH">pic.twitter.com/fiShvlN8QH</a></p>— Xe Iaso (@theprincessxena) <a href="https://twitter.com/theprincessxena/status/1508567556759728141?ref_src=twsrc%5Etfw">March 28, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
|
|
||||||
|
|
||||||
So then I took a good solid look at the rest of the 3D printed part to see if I could improve on anything else before I sent it to another round of the printer. The last stand took _14 hours_ to print and used a lot of material. I want to avoid waste.
|
|
||||||
|
|
||||||
Something I noticed is that the front of the print where all the cables come out was a bit too thin. All 5 of the cables wouldn't fit in there (my braided cables must have been thicker than the ones that the original modeler used). So again I grabbed a few platonic solids and managed to make it work out:
|
|
||||||
|
|
||||||
```scad
|
|
||||||
// widen the paths
|
|
||||||
color("green") translate([0, -16, 1.3]) rotate([0, 0, 90]) cube([10, 57, 7.8], center = true);
|
|
||||||
color("green") translate([0, 0, 1.7]) rotate([0, 0, 0]) cube([25, 30, 7], center = true);
|
|
||||||
```
|
|
||||||
|
|
||||||
<blockquote class="twitter-tweet" data-conversation="none" data-dnt="true"><p lang="und" dir="ltr"><a href="https://t.co/pKAVtiPfDS">pic.twitter.com/pKAVtiPfDS</a></p>— Xe Iaso (@theprincessxena) <a href="https://twitter.com/theprincessxena/status/1508568858650685440?ref_src=twsrc%5Etfw">March 28, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
|
|
||||||
|
|
||||||
Then I wanted to add some wedges into the underside of the part to help me get the print off the bed. Most people have a problem with bed adhesion being too little. I have too much bed adhesion. So I added some angled rectangles:
|
|
||||||
|
|
||||||
```scad
|
|
||||||
// wedges to help get the print off the bed
|
|
||||||
color([1, 1, 0]) translate([-120, 0, 0]) rotate([15, 0, 90]) cube([10, 11, 2], center = true); // right
|
|
||||||
color([1, 1, 0]) translate([120, 0, 0]) rotate([-15, 0, 90]) cube([10, 11, 2], center = true); // left
|
|
||||||
color([1, 1, 0]) translate([0, -85, 0]) rotate([0, 15, 90]) cube([10, 11, 2], center = true); // back
|
|
||||||
color([1, 1, 0]) translate([60, 56, 1]) rotate([0, -15, 90]) cube([10, 11, 2], center = true); // front left
|
|
||||||
color([1, 1, 0]) translate([-60, 56, 1]) rotate([0, -15, 90]) cube([10, 11, 2], center = true); // front right
|
|
||||||
color([1, 1, 0]) translate([32.5, 41, 1]) rotate([0, -15, 130]) cube([10, 11, 2], center = true); // front left inner
|
|
||||||
color([1, 1, 0]) translate([-32.5, 41, 1]) rotate([0, -15, 60]) cube([10, 11, 2], center = true); // front right inner
|
|
||||||
```
|
|
||||||
|
|
||||||
<blockquote class="twitter-tweet" data-conversation="none" data-dnt="true"><p lang="und" dir="ltr"><a href="https://t.co/XUQ9ZeYk1H">pic.twitter.com/XUQ9ZeYk1H</a></p>— Xe Iaso (@theprincessxena) <a href="https://twitter.com/theprincessxena/status/1508569796253827077?ref_src=twsrc%5Etfw">March 28, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
|
|
||||||
|
|
||||||
And then once I spun it around for a bit and thought it was good, I sliced it in PrusaSlicer and sent it off to Kyubey. It was going to take 14 hours, so I went off to do other things, ate dinner and then went to bed while the printer continued.
|
|
||||||
|
|
||||||
<blockquote class="twitter-tweet" data-conversation="none" data-dnt="true"><p lang="fr" dir="ltr">Diligent bean <a href="https://t.co/yPgnJA0ZdW">pic.twitter.com/yPgnJA0ZdW</a></p>— Xe Iaso (@theprincessxena) <a href="https://twitter.com/theprincessxena/status/1508397506031460352?ref_src=twsrc%5Etfw">March 28, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
|
|
||||||
|
|
||||||
Then when I woke up, Kyubey was done:
|
|
||||||
|
|
||||||
<blockquote class="twitter-tweet" data-conversation="none" data-dnt="true"><p lang="und" dir="ltr"><a href="https://t.co/2E1IS810EH">pic.twitter.com/2E1IS810EH</a></p>— Xe Iaso (@theprincessxena) <a href="https://twitter.com/theprincessxena/status/1508407046995156992?ref_src=twsrc%5Etfw">March 28, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
|
|
||||||
|
|
||||||
I was excited and chiseled the print off the bed (the wedges helped a little, but it ended up making the print look kinda weird so I don't know if I will do that again), but the hole for the middle tracker didn't fit perfectly. Everything else did though.
|
|
||||||
|
|
||||||
[If you want to get prints off your printer easier, see this video for the method we're starting to use: <br /><br /><iframe width="560" height="315" src="https://www.youtube.com/embed/VCCbzCvtRzU" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>](conversation://Mara/hacker)
|
|
||||||
|
|
||||||
I looked on my desk and found that a random pen that I had sitting around for months was about the right size, so I pushed it into and out of the hole a few times and then the cables fit perfectly. I assume some plastic was in a weird state or something.
|
|
||||||
|
|
||||||
Then I set everything up and I had my Index controller stand:
|
|
||||||
|
|
||||||
<blockquote class="twitter-tweet" data-conversation="none" data-dnt="true"><p lang="en" dir="ltr">Victory! <a href="https://t.co/A3aCtQMQt5">pic.twitter.com/A3aCtQMQt5</a></p>— Xe Iaso (@theprincessxena) <a href="https://twitter.com/theprincessxena/status/1508426229464064001?ref_src=twsrc%5Etfw">March 28, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
|
|
||||||
|
|
||||||
[I really need to get a table or something for this.](conversation://Cadey/facepalm)
|
|
||||||
|
|
||||||
I've uploaded my modified version to [Thingiverse](https://www.thingiverse.com/thing:5332988). If you want to see the OpenSCAD code, you can check it out on GitHub [here](https://github.com/Xe/3dstuff/blob/main/index_stand_hack.scad). I'm really liking OpenSCAD so far. It's very weird but it lets you do whatever you want by chaining together basic shapes to build up to what you want. I imagine I will be using it a lot in the future, especially once my husband's new sim racing gear comes in.
|
|
||||||
|
|
||||||
Having a 3D printer around is like having a very weird superpower on standby. You can compile matter in your living room, but you need a very pedantic description of what that should look like. You also can have any material you like as long as it's plastic. However when it's useful, it's a lifesaver. You can make something to fit a gap or mend something broken or even add functionality to something that lacked it. The cloud's the limit!
|
|
|
@ -1,5 +1,5 @@
|
||||||
---
|
---
|
||||||
title: "Goodbye Kubernetes"
|
title: "</kubernetes>"
|
||||||
date: 2021-01-03
|
date: 2021-01-03
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
@ -415,7 +415,7 @@ world. To use a private repo, your flake input URL should look something like
|
||||||
this:
|
this:
|
||||||
|
|
||||||
```
|
```
|
||||||
git+ssh://git@github.com:user/repo
|
ssh+git://git@github.com:user/repo
|
||||||
```
|
```
|
||||||
|
|
||||||
[I'm pretty sure you could use private git repos outside of flakes, however it
|
[I'm pretty sure you could use private git repos outside of flakes, however it
|
||||||
|
|
|
@ -1,36 +1,32 @@
|
||||||
---
|
---
|
||||||
title: "Nix Flakes: Exposing and using NixOS Modules"
|
title: "Nix Flakes: Exposing and using NixOS Modules"
|
||||||
date: 2022-04-07
|
date: 2022-03-31
|
||||||
series: nix-flakes
|
series: nix-flakes
|
||||||
tags:
|
tags:
|
||||||
- nixos
|
- nixos
|
||||||
vod:
|
vod:
|
||||||
twitch: https://www.twitch.tv/videos/1437346416
|
twitch: https://www.twitch.tv/videos/1437346416
|
||||||
youtube: https://youtu.be/wCZ9SwmgSck
|
youtube: TODO-link
|
||||||
---
|
---
|
||||||
|
|
||||||
Nix flakes allow you to expose NixOS modules. NixOS modules are templates for
|
Nix flakes allow you to expose NixOS modules. NixOS modules are templates for
|
||||||
system configuration and they are the basis of how you configure NixOS. Today
|
system configuration and they are the basis of how you configure NixOS. Today
|
||||||
we're going to take our Nix flake [from the last
|
we're going to take our Nix flake [from the last
|
||||||
article](/blog/nix-flakes-2-2022-02-27) and write a NixOS module for it so that
|
article](/blog/nix-flakes-2-2022-02-27) and write a NixOS module for it so that
|
||||||
we can deploy it to a container running locally. In the next post we will deploy
|
we can deploy it to a server.
|
||||||
this to a server.
|
|
||||||
|
|
||||||
[If you haven't read <a href="/blog/series/nix-flakes">the other articles in
|
[If you haven't read <a href="/blog/series/nix-flakes">the other articles in
|
||||||
this series</a>, you probably should. This article builds upon the previous
|
this series</a>, you probably should. This article builds upon the previous
|
||||||
ones.](conversation://Mara/hacker)
|
ones.](conversation://Mara/hacker)
|
||||||
|
|
||||||
NixOS modules are building blocks that let you configure NixOS servers. Modules
|
NixOS modules are the main building block of how NixOS servers are configured.
|
||||||
expose customizable options that expand out into system configuration.
|
They are like lego blocks that help you build up a server from off the shelf
|
||||||
Individually, each module is fairly standalone and self-contained, but they
|
parts. A module describes a desired system state and they build off of eachother
|
||||||
build up together into your server configuration like a bunch of legos build
|
in order to end up with a more elaborate result.
|
||||||
into a house. Each module describes a subset of your desired system
|
|
||||||
configuration and any options relevant to that configuration.
|
|
||||||
|
|
||||||
[You can think about them like Ansible playbooks, but NixOS modules describe the
|
[You can think about them like Ansible playbooks, but NixOS modules describe the
|
||||||
desired end state instead of the steps you need to get to that end
|
desired end state instead of the steps you need to get to that end
|
||||||
state. It's the end result of evaluating all of your options against all of the
|
state.](conversation://Mara/hacker)
|
||||||
modules that you use in your configuration.](conversation://Mara/hacker)
|
|
||||||
|
|
||||||
NixOS modules are functions that take in the current state of the system and
|
NixOS modules are functions that take in the current state of the system and
|
||||||
then return things to add to the state of the system. Here is a basic NixOS
|
then return things to add to the state of the system. Here is a basic NixOS
|
||||||
|
@ -71,47 +67,9 @@ nix-repl> { foo = 1; } // { bar = 2; }
|
||||||
{ bar = 2; foo = 1; }
|
{ bar = 2; foo = 1; }
|
||||||
```
|
```
|
||||||
|
|
||||||
<xeblog-conv name="Mara" mood="hacker">
|
|
||||||
Important pro tip: the merge operator is NOT recursive. If you try to do
|
|
||||||
something like:
|
|
||||||
|
|
||||||
```
|
|
||||||
nix-repl> foo = { bar = { baz = "foo"; }; }
|
|
||||||
nix-repl> (foo // { bar = { spam = "eggs"; }; }).bar
|
|
||||||
```
|
|
||||||
|
|
||||||
You will get:
|
|
||||||
|
|
||||||
```
|
|
||||||
{ spam = "eggs"; }
|
|
||||||
```
|
|
||||||
|
|
||||||
And not:
|
|
||||||
|
|
||||||
```
|
|
||||||
{ baz = "foo"; spam = "eggs"; }
|
|
||||||
```
|
|
||||||
|
|
||||||
This is because the `//` operator prefers things in the right hand side over the
|
|
||||||
left hand side if both conflict. To recursively merge two attribute sets (using
|
|
||||||
all elements from both sides), use
|
|
||||||
[lib.recursiveUpdate](https://nixos.org/manual/nixpkgs/stable/#function-library-lib.attrsets.recursiveUpdate):
|
|
||||||
|
|
||||||
```
|
|
||||||
nix-repl> (pkgs.lib.recursiveUpdate foo bar).bar
|
|
||||||
{ baz = "foo"; spam = "eggs"; }
|
|
||||||
```
|
|
||||||
|
|
||||||
</xeblog-conv>
|
|
||||||
|
|
||||||
We will use this to add the container configuration to the flake at the end of
|
We will use this to add the container configuration to the flake at the end of
|
||||||
the flake.nix file. We need to do this because the upper part of the flake with
|
the flake.nix file. At the end of your flake.nix (just before the final closing
|
||||||
the `forAllSystems` call will generate a bunch of system-specific attributes for
|
`}`), there should be a line that looks like this:
|
||||||
each system we support. NixOS configurations don't support this level of
|
|
||||||
granularity.
|
|
||||||
|
|
||||||
At the end of your flake.nix (just before the final closing `}`), there should
|
|
||||||
be a line that looks like this:
|
|
||||||
|
|
||||||
```nix
|
```nix
|
||||||
});
|
});
|
||||||
|
@ -250,20 +208,9 @@ config = mkIf cfg.enable {
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
<xeblog-conv name="Mara" mood="hacker">
|
[NOTE: You will want to be sure to do the following things to your copy of
|
||||||
NOTE: If you have been following along since before this article was published,
|
gohello: <ul><li>Move the definition of `defaultPackage` into the `packages` attribute set with the name `default` </li><li>Update `defaultApp` and the other entries to point to `self.packages.${system}.default` instead of `self.defaultPackage.${system}`</li></ul> We have updated previous articles and the template
|
||||||
you will want to be sure to do the following things to your copy of gohello:
|
accordingly.](conversation://Mara/hacker)
|
||||||
|
|
||||||
* Move the definition of `defaultPackage` into the `packages` attribute set with
|
|
||||||
the name `default`
|
|
||||||
* Update `defaultApp` and the other entries to point to
|
|
||||||
`self.packages.${system}.default` instead of `self.defaultPackage.${system}`
|
|
||||||
|
|
||||||
We have updated previous articles and the template accordingly. Annoyingly it
|
|
||||||
seems that this change is new enough that it isn't totally documented on the
|
|
||||||
NixOS wiki. We are working on fixing this.
|
|
||||||
|
|
||||||
</xeblog-conv>
|
|
||||||
|
|
||||||
This will do the following things:
|
This will do the following things:
|
||||||
|
|
||||||
|
@ -271,9 +218,7 @@ This will do the following things:
|
||||||
booted" and the network is active)
|
booted" and the network is active)
|
||||||
- Automatically restarts the service when it crashes
|
- Automatically restarts the service when it crashes
|
||||||
- Starts our `web-server` binary when running the service
|
- Starts our `web-server` binary when running the service
|
||||||
- Creates a random, unique user account for the service (see
|
- Creates a random user for the service
|
||||||
[here](http://0pointer.net/blog/dynamic-users-with-systemd.html) for more
|
|
||||||
information on how/why this works)
|
|
||||||
- Creates temporary, home and cache directories for the service, makes sure that
|
- Creates temporary, home and cache directories for the service, makes sure that
|
||||||
random user has permission to use them (with the specified directory modes
|
random user has permission to use them (with the specified directory modes
|
||||||
too)
|
too)
|
||||||
|
@ -346,11 +291,6 @@ nixosModule = { config, lib, pkgs, ... }:
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
[The service name is overly defensive. It's intended to avoid conflicting with
|
|
||||||
any other unit on the system named `gohello.service`. Feel free to remove this
|
|
||||||
part, it is really just defensive devops by design to avoid name
|
|
||||||
conflicts.](conversation://Mara/hacker)
|
|
||||||
|
|
||||||
Then you can add it to the container by importing our new module in its
|
Then you can add it to the container by importing our new module in its
|
||||||
configuration and activating the gohello service:
|
configuration and activating the gohello service:
|
||||||
|
|
||||||
|
@ -388,21 +328,11 @@ $ curl http://10.233.1.2 -H "Host: gohello.local.cetacean.club"
|
||||||
hello world :)
|
hello world :)
|
||||||
```
|
```
|
||||||
|
|
||||||
<xeblog-conv name="Mara" mood="hacker">
|
[As an exercise for the reader, try adding a <a
|
||||||
Exercises for the reader:
|
href="https://nixos.org/manual/nixos/stable/index.html#sec-writing-modules">nixos
|
||||||
|
option</a> that correlates to the `--bind` flag that `gohello` uses as the TCP
|
||||||
Try adding a [nixos
|
|
||||||
option](https://nixos.org/manual/nixos/stable/index.html#sec-writing-modules)
|
|
||||||
that correlates to the `--bind` flag that `gohello` uses as the TCP
|
|
||||||
address to serve HTTP from. You will want to have the type be
|
address to serve HTTP from. You will want to have the type be
|
||||||
`types.port`. If you are stuck, see
|
`types.port`.](conversation://Mara/hacker)
|
||||||
[here](https://github.com/Xe/nixos-configs/tree/master/common/services) for inspiration.
|
|
||||||
|
|
||||||
Also try adding `AmbientCapabilities = "CAP_NET_BIND_SERVICE"` and
|
|
||||||
`CapabilityBoundingSet = "CAP_NET_BIND_SERVICE"` to your `serviceConfig` and
|
|
||||||
bind `gohello` to port 80 without nginx involved at all.
|
|
||||||
|
|
||||||
</xeblog-conv>
|
|
||||||
|
|
||||||
You can delete this container with `sudo nixos-container destroy gohello` when
|
You can delete this container with `sudo nixos-container destroy gohello` when
|
||||||
you are done with it.
|
you are done with it.
|
||||||
|
@ -432,12 +362,3 @@ Next time I will cover how to install NixOS to a server and deploy system
|
||||||
configurations using [deploy-rs](https://github.com/serokell/deploy-rs). This
|
configurations using [deploy-rs](https://github.com/serokell/deploy-rs). This
|
||||||
will allow you to have your workstation build configuration for your servers and
|
will allow you to have your workstation build configuration for your servers and
|
||||||
push out all the changes from there.
|
push out all the changes from there.
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Many thanks to Open Skies for being my fearless editor that helps make these
|
|
||||||
things shine.
|
|
||||||
|
|
||||||
In part of this post I use my new Xeact-powered HTML component for some of the
|
|
||||||
conversation fragments, but the sizing was off on my iPhone when I tested it. If
|
|
||||||
you know what I am doing wrong, please [get in touch](/contact).
|
|
|
@ -1,53 +0,0 @@
|
||||||
---
|
|
||||||
title: Stop Using Politics As A Cudgel To Discourage Experimentation
|
|
||||||
date: 2022-04-21
|
|
||||||
tags:
|
|
||||||
- rant
|
|
||||||
- systemd
|
|
||||||
- communityhealth
|
|
||||||
---
|
|
||||||
|
|
||||||
So let's say you get bored one day and you decide you want to do things that god
|
|
||||||
and man have decreed impossible. Let's also say that this exact thing involves a
|
|
||||||
tool that just happens to rustle all of the jimmies (for reasons that are not
|
|
||||||
entirely clear). Then you get it all to a point where you want to submit it
|
|
||||||
upstream so you can get help experimenting with this tool.
|
|
||||||
|
|
||||||
So you submit it to upstream in the experimental branch, expecting very little
|
|
||||||
pushback so you can get help tinkering with things. But once you submit it
|
|
||||||
upstream, [all hell breaks
|
|
||||||
loose](https://gitlab.alpinelinux.org/alpine/aports/-/merge_requests/33329).
|
|
||||||
|
|
||||||
Stop using politics as a cudgel to discourage experimentation. Yes it involves
|
|
||||||
systemd. Just because you think that the tool is overcomplicated doesn't mean
|
|
||||||
that other people don't find it useful. Trying to shut down experimentation is
|
|
||||||
how you get people to leave the community or give up participating in open
|
|
||||||
source altogether.
|
|
||||||
|
|
||||||
The reactions in that thread are both disappointing and somewhat to be expected.
|
|
||||||
I don't know why people have such a negative reaction to systemd. It's just an
|
|
||||||
init system, not a religion. It wouldn't have become a good choice for so much
|
|
||||||
of the Linux ecosystem without it having solid technical merits. If it is really
|
|
||||||
that bad then the mantle of responsibility is on you for coming up with a better
|
|
||||||
option.
|
|
||||||
|
|
||||||
[No, OpenRC is not that option. It can be PART OF an option, but it is not a
|
|
||||||
competitor by itself.](conversation://Cadey/coffee)
|
|
||||||
|
|
||||||
I know I said I'd stop ranting on this blog as much, but really this stuff
|
|
||||||
grinds my gears and I feel that I should use my platform for good in this
|
|
||||||
regard. This is inexcusable. I want to reiterate that I have _no_ power in this
|
|
||||||
regard. I am just some random person on a blog that got frustrated at the
|
|
||||||
reactions to this contribution. Some pushback is acceptable. Accusing a
|
|
||||||
contributor of ignorance is inexcusable. Comments like this have no place in
|
|
||||||
open source contributions:
|
|
||||||
|
|
||||||
> SysTemD is the STD of operating systems. There is no "one little poke", you
|
|
||||||
> can't be a little bit pregnant.
|
|
||||||
|
|
||||||
Jake, if you're out there reading this: keep doing this thing. It is a fantastic
|
|
||||||
creation that I thought was impossible. You may have to soft-fork the
|
|
||||||
distribution to get this to work reliably, but I really want to see where this
|
|
||||||
rabbit-hole goes.
|
|
||||||
|
|
||||||
Keep hacking.
|
|
|
@ -1,118 +0,0 @@
|
||||||
---
|
|
||||||
title: "What To Do As A Recruiter When A Gender-diverse Person Asks You To Update Their Name"
|
|
||||||
date: 2022-04-01
|
|
||||||
---
|
|
||||||
|
|
||||||
[I really wish this was an April Fool's post. I had a few ideas planned, but
|
|
||||||
maybe you will get to see them next year.<br /><br />As a reminder, I am
|
|
||||||
speaking for myself and not for my employer.](conversation://Cadey/coffee)
|
|
||||||
|
|
||||||
This post is directed at all of the recruiters that are reading this blog. This
|
|
||||||
is a scenario that many of you may not have dealt with. After having an example
|
|
||||||
of this with a recruiter recently I figure it's a teaching moment.
|
|
||||||
|
|
||||||
I am speaking up about this because I know many others who have gone through the
|
|
||||||
same kinds of problems and have not felt safe to speak up about them. I am not
|
|
||||||
speaking for those people in this post, but I want to use my platform as a
|
|
||||||
blogger to amplify the sentiment of what I have heard over the years.
|
|
||||||
|
|
||||||
## To Recruiters
|
|
||||||
|
|
||||||
As a recruiter, if you are cold-emailing someone, please do the research to get
|
|
||||||
their name correct. If you do not and someone asks you to correct it, do it.
|
|
||||||
|
|
||||||
When gender-diverse people like me get an email that references an out of date
|
|
||||||
name, it is seen as a sign that the person sending that email has not done their
|
|
||||||
research before sending that email out into the void.
|
|
||||||
|
|
||||||
When you correct that name in your system also make sure to cancel all outgoing
|
|
||||||
automated emails to that person. The caching layer of the recruiting system may
|
|
||||||
have already drafted those emails based on a template. If they go out, this will
|
|
||||||
be seen as a _massive sign of disrespect_. It will also make the person
|
|
||||||
receiving that email question if you _actually corrected_ the name in that
|
|
||||||
system or not. It may make the recipient also question if you are just giving
|
|
||||||
them lip service to save face instead of making a genuine effort to ensure that
|
|
||||||
the recruiting system has accurate information in it.
|
|
||||||
|
|
||||||
This is not a good way to foster the kind of trust needed for a gender-diverse
|
|
||||||
person to want to choose your employer as the single point of failure for access
|
|
||||||
to medication, food and regular medical checkups. For many gender-diverse
|
|
||||||
people, changing jobs can mean an interruption of access to life-saving
|
|
||||||
medication.
|
|
||||||
|
|
||||||
You may get a slightly angry reply if you send out emails with incorrect
|
|
||||||
information. This can happen because gender-diverse people are likely to feel
|
|
||||||
like society really doesn't care about them and that they are not being
|
|
||||||
respected to have agency over their identity. To some this is a fact and not
|
|
||||||
a feeling. And with
|
|
||||||
[all](https://www.theguardian.com/us-news/2022/mar/10/idaho-bill-trans-youth-treatment-ban-passes-house)
|
|
||||||
[of](https://www.washingtonpost.com/dc-md-va/2022/03/17/texas-trans-child-abuse-investigations/)
|
|
||||||
[the](https://www.nbcnews.com/nbc-out/out-politics-and-policy/alabama-bill-seeks-ban-hormone-treatments-trans-youth-rcna18512)
|
|
||||||
[actions](https://www.hrc.org/press-releases/breaking-2021-becomes-record-year-for-anti-transgender-legislation)
|
|
||||||
governments have been taking to directly attack the freedoms and rights to
|
|
||||||
self-determination that gender-diverse people like me rely on, you can't blame
|
|
||||||
them for being fed up with the situation. It is not fun to feel like your very
|
|
||||||
existence is made out to be some black mark of doom on Western civilization. It
|
|
||||||
is even less fun to be reminded of that when reading your email inbox. Please
|
|
||||||
understand that we mean well, society is just broken in general.
|
|
||||||
|
|
||||||
The least you can do is ensure that you do _any amount of research_ to ensure
|
|
||||||
that you are using the correct name. It may be a good idea to add the following
|
|
||||||
text to your recruiting emails (before you brag about fundraising is probably
|
|
||||||
best, I tune out about then):
|
|
||||||
|
|
||||||
> If I got your name incorrect, please let me know what name/pronouns you would
|
|
||||||
> like me to update our system to use. I got this name from $SOURCE.
|
|
||||||
|
|
||||||
Adding the source of where you got that name from can help make this less
|
|
||||||
stressful for gender-diverse people. People's names are spattered everywhere
|
|
||||||
across the internet. Letting people know where you got that information from can
|
|
||||||
help them know what to fix if a fix is needed.
|
|
||||||
|
|
||||||
Some chosen names may seem "weird" due to societal biases that serve to ensure
|
|
||||||
that the primary way that people use to refer to eachother in particular are not
|
|
||||||
chosen by the people being referred to. Trust that the person on the other end
|
|
||||||
is being honest about their identity. The truth requires no belief.
|
|
||||||
|
|
||||||
If they ask you to update their pronouns, respect that and ensure you use them
|
|
||||||
without failure. Using the wrong pronouns can be seen as an even worse
|
|
||||||
disrespect than using the wrong name. You do not want this to happen if your
|
|
||||||
goal is to find people to hire.
|
|
||||||
|
|
||||||
## To Gender-diverse People
|
|
||||||
|
|
||||||
Yeah, this situation sucks. I can't disagree. You really do need to assume good
|
|
||||||
faith as much as you can. Most of these recruiter systems rely on ["data
|
|
||||||
enrichment" APIs](https://clearbit.com/) and potentially outdated mass scraping
|
|
||||||
of LinkedIn and people's blogs.
|
|
||||||
|
|
||||||
It can help if you make publicly available posts like
|
|
||||||
[this](/blog/xe-2021-08-07) that unambiguously say what you want people to call
|
|
||||||
you by. Keep it updated in case journalists decide to compare your chosen name
|
|
||||||
to mercenary groups.
|
|
||||||
|
|
||||||
Try to be as polite and direct as possible. Here is an example of how I have
|
|
||||||
asked recruiters to update their information in the past:
|
|
||||||
|
|
||||||
> Please update your files with the name "Xe Iaso" (capital I). I am
|
|
||||||
> slowly moving away from "Christine Dodrill" as the name I use to
|
|
||||||
> represent myself professionally.
|
|
||||||
|
|
||||||
If you are moving away from a "dead name", you may want to use something like
|
|
||||||
this:
|
|
||||||
|
|
||||||
> I have no record of a "Christine Dodrill" at this email address. You may want
|
|
||||||
> to look elsewhere. If you would like to proceed with me instead, here is
|
|
||||||
> information about me: https://christine.website.
|
|
||||||
|
|
||||||
Throw in your pronouns too to be safe.
|
|
||||||
|
|
||||||
[I really need to change this blog's domain, but I have such amazing SEO that I
|
|
||||||
really don't want to break it.](conversation://Cadey/coffee)
|
|
||||||
|
|
||||||
Also consider deleting the email and not replying to them. That's totally valid
|
|
||||||
too unless you are in desperate need for a new employer.
|
|
||||||
|
|
||||||
You do not need to justify speaking up about an employer having the wrong name
|
|
||||||
for you. The truth requires no belief. Speaking the truth to power is the
|
|
||||||
essence of valor, which is one of the highest forms of love.
|
|
13
config.dhall
13
config.dhall
|
@ -1,16 +1,7 @@
|
||||||
let Person =
|
let Person =
|
||||||
{ Type =
|
{ Type = { name : Text, tags : List Text, gitLink : Text, twitter : Text }
|
||||||
{ name : Text
|
|
||||||
, tags : List Text
|
|
||||||
, gitLink : Optional Text
|
|
||||||
, twitter : Optional Text
|
|
||||||
}
|
|
||||||
, default =
|
, default =
|
||||||
{ name = ""
|
{ name = "", tags = [] : List Text, gitLink = "", twitter = "" }
|
||||||
, tags = [] : List Text
|
|
||||||
, gitLink = None Text
|
|
||||||
, twitter = None Text
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let Author =
|
let Author =
|
||||||
|
|
|
@ -36,7 +36,6 @@ img {
|
||||||
|
|
||||||
.conversation-chat {
|
.conversation-chat {
|
||||||
align-self: center;
|
align-self: center;
|
||||||
min-width: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.gruvbox-dark pre, pre {
|
.gruvbox-dark pre, pre {
|
||||||
|
|
75
flake.lock
75
flake.lock
|
@ -1,75 +0,0 @@
|
||||||
{
|
|
||||||
"nodes": {
|
|
||||||
"flake-utils": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1649676176,
|
|
||||||
"narHash": "sha256-OWKJratjt2RW151VUlJPRALb7OU2S5s+f0vLj4o1bHM=",
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"rev": "a4b154ebbdc88c8498a5c7b01589addc9e9cb678",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"naersk": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": "nixpkgs"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1650265945,
|
|
||||||
"narHash": "sha256-SO8+1db4jTOjnwP++29vVgImLIfETSXyoz0FuLkiikE=",
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "naersk",
|
|
||||||
"rev": "e8f9f8d037774becd82fce2781e1abdb7836d7df",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-community",
|
|
||||||
"repo": "naersk",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1650647760,
|
|
||||||
"narHash": "sha256-Ng8CGYLSTxeI+oEux0x+tSRA6K7ydoyfJNQf56ld+Uo=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "b80f570a92d04e8ace67ff09c34aa48708a5c88c",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"id": "nixpkgs",
|
|
||||||
"type": "indirect"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs_2": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1650161686,
|
|
||||||
"narHash": "sha256-70ZWAlOQ9nAZ08OU6WY7n4Ij2kOO199dLfNlvO/+pf8=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "1ffba9f2f683063c2b14c9f4d12c55ad5f4ed887",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"id": "nixpkgs",
|
|
||||||
"ref": "nixos-unstable",
|
|
||||||
"type": "indirect"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-utils": "flake-utils",
|
|
||||||
"naersk": "naersk",
|
|
||||||
"nixpkgs": "nixpkgs_2"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": "root",
|
|
||||||
"version": 7
|
|
||||||
}
|
|
215
flake.nix
215
flake.nix
|
@ -1,215 +0,0 @@
|
||||||
{
|
|
||||||
description = "A very basic flake";
|
|
||||||
|
|
||||||
inputs = {
|
|
||||||
nixpkgs.url = "nixpkgs/nixos-unstable";
|
|
||||||
flake-utils.url = "github:numtide/flake-utils";
|
|
||||||
naersk.url = "github:nix-community/naersk";
|
|
||||||
};
|
|
||||||
|
|
||||||
outputs = { self, nixpkgs, flake-utils, naersk }:
|
|
||||||
flake-utils.lib.eachSystem [ "x86_64-linux" "aarch64-linux" ] (system:
|
|
||||||
let
|
|
||||||
pkgs = import nixpkgs { inherit system; };
|
|
||||||
naersk-lib = naersk.lib."${system}";
|
|
||||||
src = ./.;
|
|
||||||
in rec {
|
|
||||||
packages = rec {
|
|
||||||
bin = naersk-lib.buildPackage {
|
|
||||||
pname = "xesite-bin";
|
|
||||||
root = src;
|
|
||||||
buildInputs = with pkgs; [ pkg-config openssl git ];
|
|
||||||
};
|
|
||||||
|
|
||||||
config = pkgs.stdenv.mkDerivation {
|
|
||||||
pname = "xesite-config";
|
|
||||||
inherit (bin) version;
|
|
||||||
inherit src;
|
|
||||||
buildInputs = with pkgs; [ dhall ];
|
|
||||||
|
|
||||||
phases = "installPhase";
|
|
||||||
|
|
||||||
installPhase = ''
|
|
||||||
cd $src
|
|
||||||
mkdir -p $out
|
|
||||||
dhall resolve < $src/config.dhall >> $out/config.dhall
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
static = pkgs.stdenv.mkDerivation {
|
|
||||||
pname = "xesite-static";
|
|
||||||
inherit (bin) version;
|
|
||||||
inherit src;
|
|
||||||
|
|
||||||
phases = "installPhase";
|
|
||||||
|
|
||||||
installPhase = ''
|
|
||||||
mkdir -p $out
|
|
||||||
cp -vrf $src/static $out
|
|
||||||
cp -vrf $src/css $out
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
posts = pkgs.stdenv.mkDerivation {
|
|
||||||
pname = "xesite-posts";
|
|
||||||
inherit (bin) version;
|
|
||||||
inherit src;
|
|
||||||
|
|
||||||
phases = "installPhase";
|
|
||||||
|
|
||||||
installPhase = ''
|
|
||||||
mkdir -p $out
|
|
||||||
cp -vrf $src/blog $out
|
|
||||||
cp -vrf $src/gallery $out
|
|
||||||
cp -vrf $src/talks $out
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
default = pkgs.symlinkJoin {
|
|
||||||
name = "xesite-${bin.version}";
|
|
||||||
paths = [ config posts static bin ];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
devShell = pkgs.mkShell {
|
|
||||||
buildInputs = with pkgs; [
|
|
||||||
# Rust
|
|
||||||
rustc
|
|
||||||
cargo
|
|
||||||
rust-analyzer
|
|
||||||
cargo-watch
|
|
||||||
|
|
||||||
# system dependencies
|
|
||||||
openssl
|
|
||||||
pkg-config
|
|
||||||
|
|
||||||
# kubernetes deployment
|
|
||||||
dhall
|
|
||||||
dhall-json
|
|
||||||
|
|
||||||
# dependency manager
|
|
||||||
niv
|
|
||||||
|
|
||||||
# tools
|
|
||||||
ispell
|
|
||||||
];
|
|
||||||
|
|
||||||
SITE_PREFIX = "devel.";
|
|
||||||
CLACK_SET = "Ashlynn,Terry Davis,Dennis Ritchie";
|
|
||||||
RUST_LOG = "debug";
|
|
||||||
RUST_BACKTRACE = "1";
|
|
||||||
GITHUB_SHA = "devel";
|
|
||||||
};
|
|
||||||
|
|
||||||
nixosModules.bot = { config, lib, ... }:
|
|
||||||
with lib;
|
|
||||||
let cfg = config.xeserv.services.xesite;
|
|
||||||
in {
|
|
||||||
options.within.services.xesite = {
|
|
||||||
enable = mkEnableOption "Activates my personal website";
|
|
||||||
useACME = mkEnableOption "Enables ACME for cert stuff";
|
|
||||||
|
|
||||||
port = mkOption {
|
|
||||||
type = types.port;
|
|
||||||
default = 32837;
|
|
||||||
example = 9001;
|
|
||||||
description =
|
|
||||||
"The port number xesite should listen on for HTTP traffic";
|
|
||||||
};
|
|
||||||
|
|
||||||
domain = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = "xesite.akua";
|
|
||||||
example = "christine.website";
|
|
||||||
description =
|
|
||||||
"The domain name that nginx should check against for HTTP hostnames";
|
|
||||||
};
|
|
||||||
|
|
||||||
sockPath = mkOption rec {
|
|
||||||
type = types.str;
|
|
||||||
default = "/srv/within/run/xesite.sock";
|
|
||||||
example = default;
|
|
||||||
description =
|
|
||||||
"The unix domain socket that xesite should listen on";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
|
||||||
users.users.xesite = {
|
|
||||||
createHome = true;
|
|
||||||
description = "github.com/Xe/site";
|
|
||||||
isSystemUser = true;
|
|
||||||
group = "within";
|
|
||||||
home = "/srv/within/xesite";
|
|
||||||
extraGroups = [ "keys" ];
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services.xesite = {
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
|
|
||||||
serviceConfig = {
|
|
||||||
User = "xesite";
|
|
||||||
Group = "within";
|
|
||||||
Restart = "on-failure";
|
|
||||||
WorkingDirectory = "/srv/within/xesite";
|
|
||||||
RestartSec = "30s";
|
|
||||||
Type = "notify";
|
|
||||||
|
|
||||||
# Security
|
|
||||||
CapabilityBoundingSet = "";
|
|
||||||
DeviceAllow = [ ];
|
|
||||||
NoNewPrivileges = "true";
|
|
||||||
ProtectControlGroups = "true";
|
|
||||||
ProtectClock = "true";
|
|
||||||
PrivateDevices = "true";
|
|
||||||
PrivateUsers = "true";
|
|
||||||
ProtectHome = "true";
|
|
||||||
ProtectHostname = "true";
|
|
||||||
ProtectKernelLogs = "true";
|
|
||||||
ProtectKernelModules = "true";
|
|
||||||
ProtectKernelTunables = "true";
|
|
||||||
ProtectSystem = "true";
|
|
||||||
ProtectProc = "invisible";
|
|
||||||
RemoveIPC = "true";
|
|
||||||
RestrictSUIDSGID = "true";
|
|
||||||
RestrictRealtime = "true";
|
|
||||||
SystemCallArchitectures = "native";
|
|
||||||
SystemCallFilter = [
|
|
||||||
"~@reboot"
|
|
||||||
"~@module"
|
|
||||||
"~@mount"
|
|
||||||
"~@swap"
|
|
||||||
"~@resources"
|
|
||||||
"~@cpu-emulation"
|
|
||||||
"~@obsolete"
|
|
||||||
"~@debug"
|
|
||||||
"~@privileged"
|
|
||||||
];
|
|
||||||
UMask = "007";
|
|
||||||
};
|
|
||||||
|
|
||||||
script = let site = packages.default;
|
|
||||||
in ''
|
|
||||||
export SOCKPATH=${cfg.sockPath}
|
|
||||||
export DOMAIN=${toString cfg.domain}
|
|
||||||
cd ${site}
|
|
||||||
exec ${site}/bin/xesite
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
services.nginx.virtualHosts."xesite" = {
|
|
||||||
serverName = "${cfg.domain}";
|
|
||||||
locations."/" = {
|
|
||||||
proxyPass = "http://unix:${toString cfg.sockPath}";
|
|
||||||
proxyWebsockets = true;
|
|
||||||
};
|
|
||||||
forceSSL = cfg.useACME;
|
|
||||||
useACMEHost = "christine.website";
|
|
||||||
extraConfig = ''
|
|
||||||
access_log /var/log/nginx/xesite.access.log;
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -14,7 +14,6 @@ serde = { version = "1", features = ["derive"] }
|
||||||
thiserror = "1"
|
thiserror = "1"
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
tracing-futures = "0.2"
|
tracing-futures = "0.2"
|
||||||
url = "2"
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tokio = { version = "1", features = ["full"] }
|
tokio = { version = "1", features = ["full"] }
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
use std::{fs, io, path::Path};
|
|
||||||
|
|
||||||
use chrono::prelude::*;
|
use chrono::prelude::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use tracing::{debug, error, instrument};
|
use tracing::{debug, error, instrument};
|
||||||
use url::Url;
|
|
||||||
|
|
||||||
pub type Campaigns = Vec<Object<Campaign>>;
|
pub type Campaigns = Vec<Object<Campaign>>;
|
||||||
pub type Pledges = Vec<Object<Pledge>>;
|
pub type Pledges = Vec<Object<Pledge>>;
|
||||||
|
@ -64,33 +61,17 @@ pub struct User {
|
||||||
pub url: String,
|
pub url: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
|
||||||
pub struct RefreshGrant {
|
|
||||||
pub access_token: String,
|
|
||||||
pub refresh_token: String,
|
|
||||||
pub expires_in: serde_json::Value,
|
|
||||||
pub scope: serde_json::Value,
|
|
||||||
pub token_type: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type Result<T> = std::result::Result<T, Error>;
|
pub type Result<T> = std::result::Result<T, Error>;
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
#[error("json error: {0}")]
|
#[error("json error: {0:?}")]
|
||||||
Json(#[from] serde_json::Error),
|
Json(#[from] serde_json::Error),
|
||||||
|
#[error("request error: {0:?}")]
|
||||||
#[error("request error: {0}")]
|
|
||||||
Request(#[from] reqwest::Error),
|
Request(#[from] reqwest::Error),
|
||||||
|
|
||||||
#[error("{0}")]
|
|
||||||
IO(#[from] io::Error),
|
|
||||||
|
|
||||||
#[error("url parse error: {0}")]
|
|
||||||
URLParse(#[from] url::ParseError),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone, Default, Eq, PartialEq)]
|
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
|
||||||
pub struct Credentials {
|
pub struct Credentials {
|
||||||
pub client_id: String,
|
pub client_id: String,
|
||||||
pub client_secret: String,
|
pub client_secret: String,
|
||||||
|
@ -124,18 +105,12 @@ pub struct Links {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Client {
|
impl Client {
|
||||||
pub fn new() -> Result<Self> {
|
pub fn new(creds: Credentials) -> Self {
|
||||||
let mut creds = Credentials::default();
|
Self {
|
||||||
|
|
||||||
let p = Path::new(".patreon.json");
|
|
||||||
let config = fs::read_to_string(p)?;
|
|
||||||
creds = serde_json::from_str(&config)?;
|
|
||||||
|
|
||||||
Ok(Self {
|
|
||||||
cli: reqwest::Client::new(),
|
cli: reqwest::Client::new(),
|
||||||
base_url: "https://api.patreon.com".into(),
|
base_url: "https://api.patreon.com".into(),
|
||||||
creds: creds,
|
creds: creds,
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(skip(self))]
|
#[instrument(skip(self))]
|
||||||
|
@ -182,57 +157,4 @@ impl Client {
|
||||||
let data: Data<Vec<Object<Pledge>>, Object<User>> = serde_json::from_str(&data)?;
|
let data: Data<Vec<Object<Pledge>>, Object<User>> = serde_json::from_str(&data)?;
|
||||||
Ok(data.included.unwrap())
|
Ok(data.included.unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
POST www.patreon.com/api/oauth2/token
|
|
||||||
?grant_type=refresh_token
|
|
||||||
&refresh_token=<the user‘s refresh_token>
|
|
||||||
&client_id=<your client id>
|
|
||||||
&client_secret=<your client secret>
|
|
||||||
|
|
||||||
1. grab new creds
|
|
||||||
2. serialize new creds to disk
|
|
||||||
3. reload current creds in ram
|
|
||||||
4. ???
|
|
||||||
5. profit!
|
|
||||||
*/
|
|
||||||
#[instrument(skip(self))]
|
|
||||||
pub async fn refresh_token(&mut self) -> Result<()> {
|
|
||||||
let mut u = Url::parse(&self.base_url)?;
|
|
||||||
u.set_path("/api/oauth2/token");
|
|
||||||
u.query_pairs_mut()
|
|
||||||
.append_pair("grant_type", "refresh_token")
|
|
||||||
.append_pair("refresh_token", &self.creds.refresh_token)
|
|
||||||
.append_pair("client_id", &self.creds.client_id)
|
|
||||||
.append_pair("client_secret", &self.creds.client_secret);
|
|
||||||
|
|
||||||
let rg: RefreshGrant = self
|
|
||||||
.cli
|
|
||||||
.post(&u.to_string())
|
|
||||||
.header(
|
|
||||||
"Authorization",
|
|
||||||
format!("Bearer {}", self.creds.access_token),
|
|
||||||
)
|
|
||||||
.send()
|
|
||||||
.await?
|
|
||||||
.error_for_status()?
|
|
||||||
.json()
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let mut creds = self.creds.clone();
|
|
||||||
|
|
||||||
creds.access_token = rg.access_token;
|
|
||||||
creds.refresh_token = rg.refresh_token;
|
|
||||||
|
|
||||||
let p = Path::new(".patreon.json");
|
|
||||||
if p.exists() {
|
|
||||||
fs::remove_file(p)?;
|
|
||||||
}
|
|
||||||
let mut fout = fs::File::create(p)?;
|
|
||||||
serde_json::to_writer(&mut fout, &creds)?;
|
|
||||||
|
|
||||||
self.creds = creds;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
let
|
||||||
|
sources = import ./nix/sources.nix;
|
||||||
|
pkgs =
|
||||||
|
import sources.nixpkgs { overlays = [ (import sources.nixpkgs-mozilla) ]; };
|
||||||
|
dhallpkgs = import sources.easy-dhall-nix { inherit pkgs; };
|
||||||
|
dhall-yaml = dhallpkgs.dhall-yaml-simple;
|
||||||
|
dhall = dhallpkgs.dhall-simple;
|
||||||
|
xepkgs = import sources.xepkgs { inherit pkgs; };
|
||||||
|
rust = pkgs.callPackage ./nix/rust.nix { };
|
||||||
|
in with pkgs;
|
||||||
|
with xepkgs;
|
||||||
|
mkShell {
|
||||||
|
buildInputs = [
|
||||||
|
# Rust
|
||||||
|
rust
|
||||||
|
cargo-watch
|
||||||
|
|
||||||
|
# system dependencies
|
||||||
|
openssl
|
||||||
|
pkg-config
|
||||||
|
|
||||||
|
# kubernetes deployment
|
||||||
|
dhall
|
||||||
|
dhall-yaml
|
||||||
|
|
||||||
|
# dependency manager
|
||||||
|
niv
|
||||||
|
|
||||||
|
# tools
|
||||||
|
ispell
|
||||||
|
];
|
||||||
|
|
||||||
|
SITE_PREFIX = "devel.";
|
||||||
|
CLACK_SET = "Ashlynn,Terry Davis,Dennis Ritchie";
|
||||||
|
RUST_LOG = "debug";
|
||||||
|
RUST_BACKTRACE = "1";
|
||||||
|
RUST_SRC_PATH =
|
||||||
|
"${pkgs.latest.rustChannels.nightly.rust-src}/lib/rustlib/src/rust/library";
|
||||||
|
GITHUB_SHA = "devel";
|
||||||
|
}
|
|
@ -1,16 +1,7 @@
|
||||||
let Person =
|
let Person =
|
||||||
{ Type =
|
{ Type = { name : Text, tags : List Text, gitLink : Text, twitter : Text }
|
||||||
{ name : Text
|
|
||||||
, tags : List Text
|
|
||||||
, gitLink : Optional Text
|
|
||||||
, twitter : Optional Text
|
|
||||||
}
|
|
||||||
, default =
|
, default =
|
||||||
{ name = ""
|
{ name = "", tags = [] : List Text, gitLink = "", twitter = "" }
|
||||||
, tags = [] : List Text
|
|
||||||
, gitLink = None Text
|
|
||||||
, twitter = None Text
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
in [ Person::{
|
in [ Person::{
|
||||||
|
@ -29,8 +20,8 @@ in [ Person::{
|
||||||
, "istio"
|
, "istio"
|
||||||
, "typescript"
|
, "typescript"
|
||||||
]
|
]
|
||||||
, gitLink = Some "https://github.com/euforic"
|
, gitLink = "https://github.com/euforic"
|
||||||
, twitter = Some "https://twitter.com/euforic"
|
, twitter = "https://twitter.com/euforic"
|
||||||
}
|
}
|
||||||
, Person::{
|
, Person::{
|
||||||
, name = "David Roberts"
|
, name = "David Roberts"
|
||||||
|
@ -50,8 +41,8 @@ in [ Person::{
|
||||||
, "embedded"
|
, "embedded"
|
||||||
, "sql"
|
, "sql"
|
||||||
]
|
]
|
||||||
, gitLink = Some "https://github.com/ddr0"
|
, gitLink = "https://github.com/ddr0"
|
||||||
, twitter = Some "https://twitter.com/DDR_4"
|
, twitter = "https://twitter.com/DDR_4"
|
||||||
}
|
}
|
||||||
, Person::{
|
, Person::{
|
||||||
, name = "Faizan Jamil"
|
, name = "Faizan Jamil"
|
||||||
|
@ -74,7 +65,8 @@ in [ Person::{
|
||||||
, "full-stack"
|
, "full-stack"
|
||||||
, "linux"
|
, "linux"
|
||||||
]
|
]
|
||||||
, gitLink = Some "https://github.com/faizjamil"
|
, gitLink = "https://github.com/faizjamil"
|
||||||
|
, twitter = "N/A"
|
||||||
}
|
}
|
||||||
, Person::{
|
, Person::{
|
||||||
, name = "Joseph Crawley"
|
, name = "Joseph Crawley"
|
||||||
|
@ -88,8 +80,8 @@ in [ Person::{
|
||||||
, "bash"
|
, "bash"
|
||||||
, "linux"
|
, "linux"
|
||||||
]
|
]
|
||||||
, gitLink = Some "https://github.com/espe-on"
|
, gitLink = "https://github.com/espe-on"
|
||||||
, twitter = Some "https://twitter.com/espe_on_"
|
, twitter = "https://twitter.com/espe_on_"
|
||||||
}
|
}
|
||||||
, Person::{
|
, Person::{
|
||||||
, name = "nicoo"
|
, name = "nicoo"
|
||||||
|
@ -104,7 +96,7 @@ in [ Person::{
|
||||||
, "security"
|
, "security"
|
||||||
, "SDR"
|
, "SDR"
|
||||||
]
|
]
|
||||||
, gitLink = Some "https://github.com/nbraud"
|
, gitLink = "https://github.com/nbraud"
|
||||||
}
|
}
|
||||||
, Person::{
|
, Person::{
|
||||||
, name = "Prajjwal Singh"
|
, name = "Prajjwal Singh"
|
||||||
|
@ -120,8 +112,8 @@ in [ Person::{
|
||||||
, "google-cloud"
|
, "google-cloud"
|
||||||
, "typescript"
|
, "typescript"
|
||||||
]
|
]
|
||||||
, gitLink = Some "https://github.com/Prajjwal"
|
, gitLink = "https://github.com/Prajjwal"
|
||||||
, twitter = Some "https://twitter.com/prajjwalsin"
|
, twitter = "https://twitter.com/prajjwalsin"
|
||||||
}
|
}
|
||||||
, Person::{
|
, Person::{
|
||||||
, name = "Piyushh Bhutoria"
|
, name = "Piyushh Bhutoria"
|
||||||
|
@ -133,8 +125,8 @@ in [ Person::{
|
||||||
, "php"
|
, "php"
|
||||||
, "google-cloud"
|
, "google-cloud"
|
||||||
]
|
]
|
||||||
, gitLink = Some "https://github.com/Piyushhbhutoria"
|
, gitLink = "https://github.com/Piyushhbhutoria"
|
||||||
, twitter = Some "https://twitter.com/PiyushhB"
|
, twitter = "https://twitter.com/PiyushhB"
|
||||||
}
|
}
|
||||||
, Person::{
|
, Person::{
|
||||||
, name = "Ryan Casalino"
|
, name = "Ryan Casalino"
|
||||||
|
@ -151,7 +143,8 @@ in [ Person::{
|
||||||
, "flask"
|
, "flask"
|
||||||
, "unix"
|
, "unix"
|
||||||
]
|
]
|
||||||
, gitLink = Some "https://github.com/rjpcasalino"
|
, gitLink = "https://github.com/rjpcasalino"
|
||||||
|
, twitter = "N/A"
|
||||||
}
|
}
|
||||||
, Person::{
|
, Person::{
|
||||||
, name = "Jeremy White"
|
, name = "Jeremy White"
|
||||||
|
@ -170,8 +163,8 @@ in [ Person::{
|
||||||
, "google-cloud"
|
, "google-cloud"
|
||||||
, "azure"
|
, "azure"
|
||||||
]
|
]
|
||||||
, gitLink = Some "https://github.com/dudymas"
|
, gitLink = "https://github.com/dudymas"
|
||||||
, twitter = Some "https://twitter.com/dudymas"
|
, twitter = "https://twitter.com/dudymas"
|
||||||
}
|
}
|
||||||
, Person::{
|
, Person::{
|
||||||
, name = "Zachary McKee"
|
, name = "Zachary McKee"
|
||||||
|
@ -188,12 +181,14 @@ in [ Person::{
|
||||||
, "nginx"
|
, "nginx"
|
||||||
, "gunicorn"
|
, "gunicorn"
|
||||||
]
|
]
|
||||||
, gitLink = Some "https://github.com/ZacharyRMcKee"
|
, gitLink = "https://github.com/ZacharyRMcKee"
|
||||||
|
, twitter = "N/A"
|
||||||
}
|
}
|
||||||
, Person::{
|
, Person::{
|
||||||
, name = "Muazzam Kazmi"
|
, name = "Muazzam Kazmi"
|
||||||
, tags = [ "Rust", "C++", "x86assembly", "WinAPI", "Node.js", "React.js" ]
|
, tags = [ "Rust", "C++", "x86assembly", "WinAPI", "Node.js", "React.js" ]
|
||||||
, gitLink = Some "https://github.com/muazzamalikazmi"
|
, gitLink = "https://github.com/muazzamalikazmi"
|
||||||
|
, twitter = "N/A"
|
||||||
}
|
}
|
||||||
, Person::{
|
, Person::{
|
||||||
, name = "Jeffin Mathew"
|
, name = "Jeffin Mathew"
|
||||||
|
@ -207,8 +202,8 @@ in [ Person::{
|
||||||
, "javascript"
|
, "javascript"
|
||||||
, "iot"
|
, "iot"
|
||||||
]
|
]
|
||||||
, gitLink = Some "https://github.com/mjeffin"
|
, gitLink = "https://github.com/mjeffin"
|
||||||
, twitter = Some "https://twitter.com/mpjeffin"
|
, twitter = "https://twitter.com/mpjeffin"
|
||||||
}
|
}
|
||||||
, Person::{
|
, Person::{
|
||||||
, name = "Nasir Hussain"
|
, name = "Nasir Hussain"
|
||||||
|
@ -223,15 +218,22 @@ in [ Person::{
|
||||||
, "golang"
|
, "golang"
|
||||||
, "rpm packaging"
|
, "rpm packaging"
|
||||||
]
|
]
|
||||||
, gitLink = Some "https://github.com/nasirhm"
|
, gitLink = "https://github.com/nasirhm"
|
||||||
, twitter = Some "https://twitter.com/_nasirhm_"
|
, twitter = "https://twitter.com/_nasirhm_"
|
||||||
}
|
}
|
||||||
, Person::{
|
, Person::{
|
||||||
, name = "Avi Parshan"
|
, name = "Avi Parshan"
|
||||||
, tags =
|
, tags =
|
||||||
[ "python", "windows", "javascript", "html", "android", "java", "C#" ]
|
[ "python"
|
||||||
, gitLink = Some "https://github.com/avipars"
|
, "windows"
|
||||||
, twitter = Some "https://twitter.com/aviinfinity"
|
, "javascript"
|
||||||
|
, "html"
|
||||||
|
, "android"
|
||||||
|
, "java"
|
||||||
|
, "C#"
|
||||||
|
]
|
||||||
|
, gitLink = "https://github.com/avipars"
|
||||||
|
, twitter = "https://twitter.com/aviinfinity"
|
||||||
}
|
}
|
||||||
, Person:: {
|
, Person:: {
|
||||||
, name = "Tommy Nguyen"
|
, name = "Tommy Nguyen"
|
||||||
|
@ -244,13 +246,6 @@ in [ Person::{
|
||||||
, "web"
|
, "web"
|
||||||
, "google-cloud-platform"
|
, "google-cloud-platform"
|
||||||
]
|
]
|
||||||
, gitLink = Some "https://github.com/remyabel"
|
, gitLink = "https://github.com/remyabel"
|
||||||
}
|
|
||||||
, Person::{
|
|
||||||
, name = "Krish Jain"
|
|
||||||
, tags =
|
|
||||||
[ "c++", "linux", "c", "python", "ios", "nlp", "machine learning" ]
|
|
||||||
, gitLink = Some "https://github.com/Krish-sysadmin"
|
|
||||||
, twitter = Some "https://twitter.com/krishjain02"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
use crate::{post::Post, signalboost::Person};
|
use crate::{post::Post, signalboost::Person};
|
||||||
use color_eyre::eyre::Result;
|
use color_eyre::eyre::Result;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::{
|
use std::{fs, path::PathBuf};
|
||||||
fs,
|
|
||||||
path::{Path, PathBuf},
|
|
||||||
};
|
|
||||||
use tracing::{error, instrument};
|
use tracing::{error, instrument};
|
||||||
|
|
||||||
pub mod markdown;
|
pub mod markdown;
|
||||||
|
@ -12,26 +9,25 @@ pub mod poke;
|
||||||
|
|
||||||
#[derive(Clone, Deserialize)]
|
#[derive(Clone, Deserialize)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
|
#[serde(rename = "clackSet")]
|
||||||
|
pub(crate) clack_set: Vec<String>,
|
||||||
pub(crate) signalboost: Vec<Person>,
|
pub(crate) signalboost: Vec<Person>,
|
||||||
|
pub(crate) port: u16,
|
||||||
#[serde(rename = "resumeFname")]
|
#[serde(rename = "resumeFname")]
|
||||||
pub(crate) resume_fname: PathBuf,
|
pub(crate) resume_fname: PathBuf,
|
||||||
|
#[serde(rename = "webMentionEndpoint")]
|
||||||
|
pub(crate) webmention_url: String,
|
||||||
#[serde(rename = "miToken")]
|
#[serde(rename = "miToken")]
|
||||||
pub(crate) mi_token: String,
|
pub(crate) mi_token: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument]
|
#[instrument]
|
||||||
async fn patrons() -> Result<Option<patreon::Users>> {
|
async fn patrons() -> Result<Option<patreon::Users>> {
|
||||||
let p = Path::new(".patreon.json");
|
use patreon::*;
|
||||||
if !p.exists() {
|
let creds: Credentials = envy::prefixed("PATREON_")
|
||||||
info!("{:?} does not exist", p);
|
.from_env()
|
||||||
return Ok(None);
|
.unwrap_or(Credentials::default());
|
||||||
}
|
let cli = Client::new(creds);
|
||||||
|
|
||||||
let mut cli = patreon::Client::new()?;
|
|
||||||
|
|
||||||
if let Err(why) = cli.refresh_token().await {
|
|
||||||
error!("error getting refresh token: {}", why);
|
|
||||||
}
|
|
||||||
|
|
||||||
match cli.campaign().await {
|
match cli.campaign().await {
|
||||||
Ok(camp) => {
|
Ok(camp) => {
|
||||||
|
|
|
@ -232,7 +232,7 @@ async fn main() -> Result<()> {
|
||||||
let _ = std::fs::remove_file(&sockpath);
|
let _ = std::fs::remove_file(&sockpath);
|
||||||
let uds = UnixListener::bind(&sockpath)?;
|
let uds = UnixListener::bind(&sockpath)?;
|
||||||
axum::Server::builder(ServerAccept { uds })
|
axum::Server::builder(ServerAccept { uds })
|
||||||
.serve(app.into_make_service_with_connect_info::<UdsConnectInfo>())
|
.serve(app.into_make_service_with_connect_info::<UdsConnectInfo, _>())
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
|
|
|
@ -36,7 +36,7 @@ impl Into<jsonfeed::Item> for Post {
|
||||||
.date_published(self.date.to_rfc3339())
|
.date_published(self.date.to_rfc3339())
|
||||||
.author(
|
.author(
|
||||||
jsonfeed::Author::new()
|
jsonfeed::Author::new()
|
||||||
.name("Xe Iaso")
|
.name("Christine Dodrill")
|
||||||
.url("https://christine.website")
|
.url("https://christine.website")
|
||||||
.avatar("https://christine.website/static/img/avatar.png"),
|
.avatar("https://christine.website/static/img/avatar.png"),
|
||||||
);
|
);
|
||||||
|
@ -83,7 +83,8 @@ impl Post {
|
||||||
|
|
||||||
async fn read_post(dir: &str, fname: PathBuf, cli: &Option<mi::Client>) -> Result<Post> {
|
async fn read_post(dir: &str, fname: PathBuf, cli: &Option<mi::Client>) -> Result<Post> {
|
||||||
debug!(
|
debug!(
|
||||||
"loading {}",
|
"loading {}/{}",
|
||||||
|
dir,
|
||||||
fname.clone().into_os_string().into_string().unwrap()
|
fname.clone().into_os_string().into_string().unwrap()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -6,9 +6,9 @@ pub struct Person {
|
||||||
pub tags: Vec<String>,
|
pub tags: Vec<String>,
|
||||||
|
|
||||||
#[serde(rename = "gitLink")]
|
#[serde(rename = "gitLink")]
|
||||||
pub git_link: Option<String>,
|
pub git_link: String,
|
||||||
|
|
||||||
pub twitter: Option<String>,
|
pub twitter: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -21,12 +21,7 @@
|
||||||
<div class="cell -4of12 content">
|
<div class="cell -4of12 content">
|
||||||
<big>@person.name</big>
|
<big>@person.name</big>
|
||||||
<p>@for tag in person.tags { @tag }</p>
|
<p>@for tag in person.tags { @tag }</p>
|
||||||
@if person.git_link.is_some() {
|
<a href="@person.git_link">GitHub</a> - <a href="@person.twitter">Twitter</a>
|
||||||
<a href="@person.git_link.unwrap()">GitHub</a>
|
|
||||||
}
|
|
||||||
@if person.twitter.is_some() {
|
|
||||||
<a href="@person.twitter.unwrap()">Twitter</a>
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue