Compare changes

Choose any two refs to compare.

-4
.git-crypt/.gitattributes
···
-
# Do not edit this file. To specify the files to encrypt, create your own
-
# .gitattributes file in the directory where your files are.
-
* !filter !diff
-
*.gpg binary
···
.git-crypt/keys/default/0/7595B36DF6C2E95E10E528662932BA0FA3DDD7D6.gpg

This is a binary file and will not be displayed.

-1
.gitattributes
···
-
*.cry filter=git-crypt diff=git-crypt
···
+2 -1
.github/workflows/build.yaml
···
run: nix build .#nixosConfigurations."${{ matrix.host }}".config.system.build.toplevel
- name: Setup attic and push to cache
run: |
nix run github:zhaofengli/attic#default login nbsm https://nonbunary.soopy.moe ${access_token}
-
nix run github:zhaofengli/attic#default push gensokyo-${{ matrix.host }} result
env:
access_token: ${{ secrets.ATTIC_ACCESS_TOKEN }}
continue-on-error: true
···
run: nix build .#nixosConfigurations."${{ matrix.host }}".config.system.build.toplevel
- name: Setup attic and push to cache
+
if: ${{ github.event_name != 'pull_request' }}
run: |
nix run github:zhaofengli/attic#default login nbsm https://nonbunary.soopy.moe ${access_token}
+
nix run github:zhaofengli/attic#default push gensokyo-systems result
env:
access_token: ${{ secrets.ATTIC_ACCESS_TOKEN }}
continue-on-error: true
-50
.github/workflows/docs.yaml
···
-
name: Deploy repo docs page with Jekyll and GH Pages
-
-
on:
-
# Runs on pushes targeting the default branch
-
push:
-
branches: ["main"]
-
-
# Allows you to run this workflow manually from the Actions tab
-
workflow_dispatch:
-
-
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
-
permissions:
-
contents: read
-
pages: write
-
id-token: write
-
-
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
-
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
-
concurrency:
-
group: "pages"
-
cancel-in-progress: false
-
-
jobs:
-
# Build job
-
build:
-
runs-on: ubuntu-latest
-
steps:
-
- name: Checkout
-
uses: actions/checkout@v3
-
- name: Setup Pages
-
uses: actions/configure-pages@v3
-
- name: Build with Jekyll
-
uses: actions/jekyll-build-pages@v1
-
with:
-
source: ./
-
destination: ./_site
-
- name: Upload artifact
-
uses: actions/upload-pages-artifact@v2
-
-
# Deployment job
-
deploy:
-
environment:
-
name: github-pages
-
url: ${{ steps.deployment.outputs.page_url }}
-
runs-on: ubuntu-latest
-
needs: build
-
steps:
-
- name: Deploy to GitHub Pages
-
id: deployment
-
uses: actions/deploy-pages@v2
···
+4
.github/workflows/update-lockfile.yaml
···
name: "Update Flake Lockfile"
on:
workflow_dispatch:
schedule:
···
name: "Update Flake Lockfile"
+
permissions:
+
pull-requests: write
+
contents: write
+
on:
workflow_dispatch:
schedule:
+23
.sops.yaml
···
···
+
keys:
+
# maintainers
+
- &soopyc_mpxl7a age10rkyshu0lswdqyvun4cs9cekm9zt4fw5c8ssa38tn3lukgcahcvsltnqx2
+
- &soopyc_pgp302 8F3B277901484C6EA7E63F82D539637D518022C6
+
# - &soopyc_age302 age1yubikey1qgmfcf0vddslyza7djdekjjk3t3u29d474c5xscmcdye8x3spvhlxxj23xz
+
# failed to parse input as Bech32-encoded age public key: malformed recipient "age1yubikey1qgmfcf0vddslyza7djdekjjk3t3u29d474c5xscmcdye8x3spvhlxxj23xz": invalid type "age1yubikey"
+
+
# Hosts
+
- &koumakan_ssh age18h7hya5terghrwawgpny28swlat2nqkdrfd4clk0svujqlz9xfusd3zeqt
+
+
default_group: &default_group
+
pgp:
+
- *soopyc_pgp302
+
age:
+
# - *soopyc_age302
+
- *soopyc_mpxl7a
+
+
creation_rules:
+
- path_regex: creds/sops/koumakan.yaml
+
key_groups:
+
- <<: *default_group
+
age:
+
- *koumakan_ssh
+2
README.md
···
# Cow
![a yak on some grass](docs/quaritsch-photography-1_6rJHQ2Gmw-unsplash.jpg)
···
+
[![Check and Build configuration](https://github.com/soopyc/nix-on-koumakan/actions/workflows/build.yaml/badge.svg?branch=main)](https://github.com/soopyc/nix-on-koumakan/actions/workflows/build.yaml)
+
# Cow
![a yak on some grass](docs/quaritsch-photography-1_6rJHQ2Gmw-unsplash.jpg)
+3
creds/sops/.gitattributes
···
···
+
# to use, make sure `sops` is in your path and run
+
# git config diff.sopsdiff.textconv "sops -d"
+
*.yaml diff=sopsdiff
+68
creds/sops/koumakan.yaml
···
···
+
comment_unencrypted: See https://github.com/Mic92/sops-nix/issues/120 for synapse.yaml quirks
+
synapse.yaml: ENC[AES256_GCM,data:eQsUW4mwbSPzsoi8HIEngfU5x/PEaqPxvx1AXXJJj7WDX9RsPtQOqQJjuTAEPtz32Hm1nob+VVYuzAXXfCO8Cd0CIHG+xlV4cWNc4JB8wj1YgtMJu9J3yC7iv3HMULT0TL8MxmwWYKqSPKIVarLVN5gQl1G1SAfxEK3ET6qtmkmCD8y6ZVM/84fTR5lxpLe82CaplbUHXEHKk51XwGYLSp5IZsPwtMMFhYuaoqCsEVr65IiSozbD4LKddYNQKUlYmkSfThQsoPpe9ixE7+HS11S+LklyP1q3usWTfOPsQS8k5NJdcGkrCH2A4ddjWkDBAzdav3qauYoQEvbMd8BpoDqD/67lKuvoyXqDoPf5sLrQcxcUl8ObTI1I8zWhabGa9uTuiaTd3wYdMhvMvs/KIfPXNDqcBuIY9sR6LQmY2Zb9+FtYiQVnrr0XmzjB59oN023y1xC/xqkgRyXysndhnj4P1Q+PYbOMQi7hwAjM5xMk/mLkpLn41Ju4u0MqDwHSxA/NXbsEBp/u3Tim2jsrMZqjRZwQHt1n/gtMjm2cMTminM99c/fV2fcvAmcNB9u1KWgEte1JjQSRftg7pkaznYlfrQLyCQYghVu3kgeAJCaSPMewHVWOF/onTauNHYFMlJ8VDUuYOnt2LNJUk1Wap5dGfKm7661mTeYB8aw0h3111YEViuGkSp+oM5A8X6CBI6YsYYOWq5Qd+A3fFJVpcf9hhhdx0JsRmR3EZOupIVx5Y4ruuA6ipj/xMDRNfTZjqukpn3Y1s5xTjUYEo3moLdgd1PYxAVIY/KjPn31pmRThGG1NZpYHZ1yjmptVydtqf/tTd32i3e0WjIjUEZD1NE7Z5AiWJ+XAEaE3S804C6QxN1jHZvqIokA9C4HO+R/es1uDyf2KDvxf1It0hMLg7CAnq1AQcbLCDqXXZaqibSRNfv09lO4jZ3vBe3owvd1wGbK513nqC6m2gh8YDYiHdw7UlXMbMP9+,iv:fvaZQ66VKU+uzvn5AwTIFgzz+F2kJ8/QR2AfmynRfGU=,tag:8c/cAMZ6c7h3J+shh7l7tw==,type:str]
+
matrix-signing-key: ENC[AES256_GCM,data:u6miE2oM3TUXaQ7wc776SwSMaOAxJOVlpl2kBW+AjI/aDH5vcGBp0L0uTpZbVfOtIe+RDNEv5E/mKA==,iv:abvwkrNe324QCbWLwiPY0UwqezS0wbyk2Fvi0vs3SI0=,tag:ZmpDB9LHbezQrxuwHNgpRg==,type:str]
+
akkoma:
+
dist:
+
cookie: ENC[AES256_GCM,data:5jpsa4KsOAoCMGAt9laK9ioVTJfuT9+viKva8wDWRnAimVY6jDoNr4+hxVty6yQAAfSJYA7ddTxaSCEjnJtneg==,iv:V8+MpX/IEc57zEfhNGX5f+eMyipraaXDKPDNDOy0Ieo=,tag:+xCy18Ni8F5wYkO/4NbSzw==,type:str]
+
endpoint:
+
secret_base: ENC[AES256_GCM,data:l34Rj4iIQIykgzTLJolqWLQQz5pcfa0o5U/ZMKeNc2CBQedxiMXYrLSNOx6OuV38aqoOolccJEOSiVjfbTawtg==,iv:/x0ydo2gOPrhIZI7at877bzfFgMpraauozfLq95aHCk=,tag:RQI4aeLiAkAcWYlwLaTj5w==,type:str]
+
salt: ENC[AES256_GCM,data:CP4805tG05A=,iv:aSun7ABJdbDQrFcrGQMM9H1/7d5lJqeMwO08gUYrD2A=,tag:ikhxbijsqyBFJs02j2j/vw==,type:str]
+
live_view:
+
salt: ENC[AES256_GCM,data:4fKLclucoV0=,iv:ZvWKutuMTOm2X8w8a0fOTq+ldrXemayIUY2PUcurY80=,tag:qkIB1gPCI5HO0G0mLEsV+w==,type:str]
+
joken_default_signer: ENC[AES256_GCM,data:myCEFUkf8s1YNQAigjxygRYvbwkpsv7cqgs00fARe9nxSFl2wveWM5JcfOnoVPwVBVV2GaAjFe4oMWXkaTPtqg==,iv:Yk1f/fzzbruW64mvTTeiyTlbrOO/G47CKKfr9BLtQ5g=,tag:QLpM22ec+VWtkjx5U/mzCw==,type:str]
+
search:
+
meili:
+
host_unencrypted: https://megumin.soopy.moe/
+
key: ENC[AES256_GCM,data:00TLCUneHn7NcSK1joURfIzxNFWyOBf/0/fceOn4RMcMt59dZz9LOvbs3F8B0vcH7tf/eUi3SnhYJNyRdPklyw==,iv:t0kQUCmjhFw8Z2CTmYOPUNFvyiYfsXETU8GSxhRR5KE=,tag:CPjtd7jQzgHJDrsIjHlVFQ==,type:str]
+
vapid:
+
pub: ENC[AES256_GCM,data:HYMKjhVCW/7DsMfPPssEduuwWnFezH4OOq4hfAovI82RUPsfVEKhgvkI9INY8hArAb/AIfyyxZhVx+bd2QkPlnASz51L7MxPtkPfZNUKqafjlMmK0nwH,iv:154BP5EmBqnKyf9BND2laKV3caVxa34MCRzrsg6/dik=,tag:wHLYdI6oQXPUzbw8dSxgwg==,type:str]
+
key: ENC[AES256_GCM,data:t+da4NLEPZBMvq3MQkFEr+Fsj3XMGPMFKUWwbHDWNJAyuUZuiVcn3zX0kw==,iv:yQLu5CFl73GCojMBa2II6OhLrNNinsiVG1aPOAx+HtM=,tag:n0oelXaNFvilyee+MRSB8A==,type:str]
+
postgres:
+
hostname: ENC[AES256_GCM,data:rFEnhnn/Bw85,iv:GM2SH4Gkvt8tLG8AYIKxfHTZvB1sT+hgIoqkiViH6Es=,tag:yyGY9/nS9WFcJTGXlYpz6Q==,type:str]
+
database_unencrypted: akkoma
+
username: ENC[AES256_GCM,data:6skzOqv1,iv:OQ6zNmDn0uqKqNKEqOHWY6VBuT/4/CHog7b0Pf0TAPM=,tag:8HLmGykXg2V4t4RHzB8yaA==,type:str]
+
password: ENC[AES256_GCM,data:J3OewVKr2A3TlT7ZUTk7tQr4olFs7bKx47Lus4LGbwGAZfNEmyk9coFTeQ8L/EJ0hpLfPfD1OcGBc+p0ZWK/XQ==,iv:UFe/3H/AfTgSlJikHqE1IED3zINjDuOs5niXpGWXGYE=,tag:MvT0z3TMs1dehg4gp54MyQ==,type:str]
+
smtp:
+
username: ENC[AES256_GCM,data:N7XbQkngWcUGzn/SR4AXCQ==,iv:wBXWtRYawOkjumsvTPcKfvL95CCB+RbsEyJv0YUG3WA=,tag:vGQREe+Cv0ITTxszl21J2g==,type:str]
+
password: ENC[AES256_GCM,data:oU/aWkVmDU8WJhmwqOcXJ/EngiF7hvfUzPwpdjwkyh7Dw50dyG5AY7b2+hh6LIv9RZrN4yU+fXPAYr1W21OG/A==,iv:ds8Bg9JSJdNHUXh0FvD5a4pquyRnIXowcsJcVV1TyB4=,tag:JoYqas2RGSv8xyvJT9wHAQ==,type:str]
+
relay: ENC[AES256_GCM,data:F2NnRLSTO5kmbWy4fx0=,iv:omnyn+Xa/cjqK+9l5bI573aR2p7UsUvqGX5ZQGf3CD0=,tag:t4u/jLQ1nZchyxf3WrhW6w==,type:str]
+
sops:
+
kms: []
+
gcp_kms: []
+
azure_kv: []
+
hc_vault: []
+
age:
+
- recipient: age10rkyshu0lswdqyvun4cs9cekm9zt4fw5c8ssa38tn3lukgcahcvsltnqx2
+
enc: |
+
-----BEGIN AGE ENCRYPTED FILE-----
+
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBYMFBMZHdrR2ZMaEErZVlE
+
RmRZNnoxRVpVSDc5Rlg3MmhiVkxnK1NkNmljCjBsNE5oejcyOTRJRVVvdzJsMmw3
+
SGdyaUM1T0JvN3lDQjd4V054MWc1UjQKLS0tIDVvSndXZ29KSC8yUW5SRjdIcEZL
+
WkFkK1hsdzRnMmRBdDI0dWU3a1hBOEUKf+pJ6PAH1tPLXG14ghG4gxHpVN4D6TU1
+
GHCvsS5qNW8Cjis/Ubb3PHJfFiN4quN3rLaM/Ivkl5G1gzf9cGSDyQ==
+
-----END AGE ENCRYPTED FILE-----
+
- recipient: age18h7hya5terghrwawgpny28swlat2nqkdrfd4clk0svujqlz9xfusd3zeqt
+
enc: |
+
-----BEGIN AGE ENCRYPTED FILE-----
+
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBXbVhFQXJ5ZWVVZTJocmpn
+
Q1VFc01mcnZLRGtqQVF0VjB3RU1DL0phaFVVCkFmU2w3WlhuTDFHYnF5VC9TM0xz
+
VGdSSVpVbkN1Tlh4WnQxdHJkQU42dGMKLS0tIFVnVERoQWk1N1dmdWk0KzA0R1ZG
+
cHJ5aWIrQ2Zrb1dhbC9yZ1lIMU1jbzgK4mx+S5bF6KBMe6+TrSZfaBcuWEg9cHyd
+
tbJty1zxS9pndA/u3qz5EJxDouiAODvyAR07yeegtEcbw1FlG6W/gA==
+
-----END AGE ENCRYPTED FILE-----
+
lastmodified: "2023-09-14T17:13:38Z"
+
mac: ENC[AES256_GCM,data:Jyx0f+w9fJ+B1lz4jVVkcKxd1xUh3FzxDhk+KaxJLVh0BG/1d8Nx0/cOnxZV1FfJkn5Z2wYiLzBPSvJKe8MjlExOSH1mIAnuXcSP6dvXp21bgX17CXM6OP91Ny6IvwSZriqs6EIpWOkZNdxsEnySwtECoQfgs09ZnA4qmbtb01U=,iv:XHnY20d0WsnaECF1/68eu2/xcGLGeGnzba+/kBxDcc0=,tag:alo+8B2fVHon0lHGsQSUyQ==,type:str]
+
pgp:
+
- created_at: "2023-09-08T14:11:19Z"
+
enc: |-
+
-----BEGIN PGP MESSAGE-----
+
+
wV4DAxCcDC4ukRQSAQdA6IXTpPTgsoAuUSW0NqFw4MpqX4j3Wt9IqcGbrDobZGIw
+
FFZDSKuMgO7ADZCFoADJ9OWOQBUyE3htwkXWjT/NQdBbVX3nuANbsfRfTdPN5NJt
+
0lEB30Vck2fEXQsIGrIeg3pPRBl3U/z7F35tw+79EFZ5yOrAsOzSn3wzNA549/T7
+
dEVnej/86D4ZxtMqMjVB2NjsXrphqd7ENozlljMM6QKkjtg=
+
=juKF
+
-----END PGP MESSAGE-----
+
fp: 8F3B277901484C6EA7E63F82D539637D518022C6
+
unencrypted_suffix: _unencrypted
+
version: 3.7.3
+2 -1
creds/ssh/cassie
···
# SmartCards
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGvCpt7yWIptJ9XFBhwVIj9zR30OzkWI976B/P5+0whD cardno:13 901 056
-
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGvCpt7yWIptJ9XFBhwVIj9zR30OzkWI976B/P5+0whD cardno:19 302 295
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICMjRM3BNkLbU57RyfUx7kOlZeBEj/NByr1PfXri82aP cardno:19 302 432
# Static devices
···
+
# If I had an option, I would not use ecdsa keys.
# SmartCards
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGvCpt7yWIptJ9XFBhwVIj9zR30OzkWI976B/P5+0whD cardno:13 901 056
+
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBJxpXpPlPEZPfnw2mIuWJEy/C/5h1bb6pIMeFsHAICQ+lLdEkbBSeDXQuA8feLN0MJw8KaB9jqrJbYgFadV/nVA= YubiKey #19302295 PIV Slot 9a
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICMjRM3BNkLbU57RyfUx7kOlZeBEj/NByr1PfXri82aP cardno:19 302 432
# Static devices
+6
docs/_config.yml
···
···
+
remote_theme: pages-themes/leap-day@v0.2.0
+
plugins:
+
- jekyll-remote-theme # add this line to the plugins list if you already have one
+
+
title: nix-on-koumakan
+
show_downloads: false
+6
docs/docs.md
···
···
+
# documentation
+
lmao bals
+
+
## table of contents
+
- [tips_n_tricks.md](./tips_n_tricks.md) Tips and tricks for nix
+
- [utils.md](./utils.md) _utils functions reference
+17 -5
docs/index.md
···
-
# documentation
-
bals
-
## table of contents
-
- [tips_n_tricks.md](./tips_n_tricks.md) Tips and tricks for nix
-
- [utils.md](./utils.md) _utils functions reference
···
+
# Cow
+
![a yak on some grass](./quaritsch-photography-1_6rJHQ2Gmw-unsplash.jpg)
+
+
*Gracefully provided by [Quaritsch Photography](https://unsplash.com/@quaritsch) on Unsplash, via https://unsplash.com/photos/1_6rJHQ2Gmw*
+
# NixOS Configuration
+
This is a bare minimum nix configuration for koumakan.
+
+
I'm still very, very new to Nix and its ecosystem so pointers to better
+
way of doing things are very much appreciated.
+
+
## docs
+
documentation and extra tips can be found [here](./docs)
+
+
couldn't find what you needed? suffer with me! see the
+
[How 2 Nix section in this repo.](https://github.com/hlissner/dotfiles#frequently-asked-questions)
+
+
โœ“โœ“โœ“โœ“โœ“โœ“โœ“โœ“โœ“โœ“โœ“โœ“โœ“โœ“โœ“โœ“โœ“โœ“โœ“โœ“โœ“โœ“โœ“โœ“โœ“โœ“โœ“โœ“โœ“โœ“โœ“โœ“โœ“โœ“โœ“โœ“โœ“โœ“โœ“โœ“โœ“โœ“โœ“โœ“โœ“โœ“
+8 -4
docs/tips_n_tricks.md
···
this document outlines things that i learned from various sources and some pure guesswork
> To learn Nix is to learn to suffer, and to learn the way of numbing the pain
-
โ€” Cassie circa. 2023
## overriding packages
the pill confused me and i thought i had to make overlays to do overrides but no
···
just don't!!!11 remove the pkgs definition. (note that this only applies to `pkgs = import nixpkgs {};`)
-
### explanation
> you shouldn't ever really import nixpkgs with an empty attrset either
>
> that causes it to fall back on guessing your system using `builtins.currentSystem`,
> which is impure and so not allowed in pure evaluation mode
-
โ€” \@getchoo
-
## Useful links
Builtin stdlib functions search engine: https://noogle.dev/
···
this document outlines things that i learned from various sources and some pure guesswork
> To learn Nix is to learn to suffer, and to learn the way of numbing the pain
+
>
+
> โ€” Cassie circa. 2023
## overriding packages
the pill confused me and i thought i had to make overlays to do overrides but no
···
just don't!!!11 remove the pkgs definition. (note that this only applies to `pkgs = import nixpkgs {};`)
+
explanation
+
> you shouldn't ever really import nixpkgs with an empty attrset either
>
> that causes it to fall back on guessing your system using `builtins.currentSystem`,
> which is impure and so not allowed in pure evaluation mode
+
>
+
> โ€” \@getchoo
+
+
# Useful links
Builtin stdlib functions search engine: https://noogle.dev/
+42 -2
docs/utils.md
···
# utility functions
## `_utils.mkVhost`
-
make virtual host with sensible defaults
pass in a set to override the defaults.
## `_utils.mkSimpleProxy`
make a simple reverse proxy
takes a set:
···
port,
protocol ? "http",
location ? "/",
-
websockets ? false
}
```
···
# utility functions
## `_utils.mkVhost`
+
`attrset -> attrset`
+
make a virtual host with sensible defaults
pass in a set to override the defaults.
+
### Example
+
```nix
+
services.nginx.virtualHosts."balls.example" = _utils.mkVhost {};
+
```
+
## `_utils.mkSimpleProxy`
+
`attrset -> attrset`
+
make a simple reverse proxy
takes a set:
···
port,
protocol ? "http",
location ? "/",
+
websockets ? false,
+
extraConfig ? {}
}
```
+
+
It is recommended to override/add attributes with `extraConfig` to
+
preserve defaults.
+
+
Items in `extraConfig` are merged verbatim to the base attrset with defaults.
+
They are overridden based on their order.
+
+
## `_utils.genSecrets`
+
`namespace[str] -> files[list[str]] -> value[attrset] -> attrset`
+
a
+
generate an attrset to be passed into sops.secrets.
+
+
### Example
+
```nix
+
{ _utils, ... }:
+
let
+
secrets = [
+
"secure_secret"
+
# this is a directory structure, so secrets will be stored as a file in /run/secrets/service/test/secret.
+
"service/test/secret"
+
];
+
in {
+
sops.secrets = _utils.genSecrets "" secrets {}; # it's recommended to use a namespace, but having none is still fine.
+
# -> sops.secrets."secure_secret" = {};
+
# sops.secrets."service/test/secret" = {};
+
sops.secrets = _utils.genSecrets "balls" ["balls_secret"] {owner = "balls"};
+
# -> sops.secrets."balls/balls_secret" = {owner = "balls";};
+
}
+
```
+
+
See https://github.com/soopyc/nix-on-koumakan/blob/b7983776143c15c91df69ef34ba4264a22047ec6/systems/koumakan/services/fedivese/akkoma.nix#L8-L34 for a more extensive example
+62 -7
flake.lock
···
"type": "github"
}
},
"flake-parts": {
"inputs": {
"nixpkgs-lib": [
···
},
"mystia": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
-
"lastModified": 1693640431,
-
"narHash": "sha256-J18gekIkOmEgbZP9Veebj9/0MQZDF2YwMAlaykH/Qsk=",
"owner": "soopyc",
"repo": "mystia",
-
"rev": "a0e49e52b8c5651340a29cf85d46b64791fb7b78",
"type": "github"
},
"original": {
···
},
"nixpkgs": {
"locked": {
-
"lastModified": 1693639988,
-
"narHash": "sha256-munyCKe2fzSPJGKz14ud3PMjDYRcsMyS3RjOj01/rNU=",
"owner": "NixOS",
"repo": "nixpkgs",
-
"rev": "6c72c63dc8aecadc1b960cd4051268c6584b2606",
"type": "github"
},
"original": {
···
"type": "github"
}
},
"pre-commit-hooks-nix": {
"inputs": {
"flake-compat": [
···
"home-manager": "home-manager",
"lanzaboote": "lanzaboote",
"mystia": "mystia",
-
"nixpkgs": "nixpkgs"
}
},
"rust-overlay": {
···
"original": {
"owner": "oxalica",
"repo": "rust-overlay",
"type": "github"
}
},
···
"type": "github"
}
},
+
"flake-compat_3": {
+
"flake": false,
+
"locked": {
+
"lastModified": 1673956053,
+
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
+
"owner": "edolstra",
+
"repo": "flake-compat",
+
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
+
"type": "github"
+
},
+
"original": {
+
"owner": "edolstra",
+
"repo": "flake-compat",
+
"type": "github"
+
}
+
},
"flake-parts": {
"inputs": {
"nixpkgs-lib": [
···
},
"mystia": {
"inputs": {
+
"flake-compat": "flake-compat_3",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
+
"lastModified": 1694357290,
+
"narHash": "sha256-Mai5saiiuBWlQzTreLtIeUJQJN9zMH/UBIKJPOqnasM=",
"owner": "soopyc",
"repo": "mystia",
+
"rev": "cfe783698ccd18cb27fb2e422917f14b82f7afc4",
"type": "github"
},
"original": {
···
},
"nixpkgs": {
"locked": {
+
"lastModified": 1694237756,
+
"narHash": "sha256-8T29BDnqRexwVy3jhEzIH9r7ROiF9I6ESVD0QLC6VXk=",
"owner": "NixOS",
"repo": "nixpkgs",
+
"rev": "1a5bda2b28ea75a96dda2c349fe6d5e7864950ee",
"type": "github"
},
"original": {
···
"type": "github"
}
},
+
"nixpkgs-stable_3": {
+
"locked": {
+
"lastModified": 1693675694,
+
"narHash": "sha256-2pIOyQwGyy2FtFAUIb8YeKVmOCcPOTVphbAvmshudLE=",
+
"owner": "NixOS",
+
"repo": "nixpkgs",
+
"rev": "5601118d39ca9105f8e7b39d4c221d3388c0419d",
+
"type": "github"
+
},
+
"original": {
+
"owner": "NixOS",
+
"ref": "release-23.05",
+
"repo": "nixpkgs",
+
"type": "github"
+
}
+
},
"pre-commit-hooks-nix": {
"inputs": {
"flake-compat": [
···
"home-manager": "home-manager",
"lanzaboote": "lanzaboote",
"mystia": "mystia",
+
"nixpkgs": "nixpkgs",
+
"sops-nix": "sops-nix"
}
},
"rust-overlay": {
···
"original": {
"owner": "oxalica",
"repo": "rust-overlay",
+
"type": "github"
+
}
+
},
+
"sops-nix": {
+
"inputs": {
+
"nixpkgs": [
+
"nixpkgs"
+
],
+
"nixpkgs-stable": "nixpkgs-stable_3"
+
},
+
"locked": {
+
"lastModified": 1693898833,
+
"narHash": "sha256-OIrMAGNYNeLs6IvBynxcXub7aSW3GEUvWNsb7zx6zuU=",
+
"owner": "Mic92",
+
"repo": "sops-nix",
+
"rev": "faf21ac162173c2deb54e5fdeed002a9bd6e8623",
+
"type": "github"
+
},
+
"original": {
+
"owner": "Mic92",
+
"repo": "sops-nix",
"type": "github"
}
},
+31 -9
flake.nix
···
{
description = "Gensokyo system configurations";
-
nixConfig = rec {
extra-substituters = [
"https://nonbunary.soopy.moe/gensokyo-global"
"https://nonbunary.soopy.moe/gensokyo-systems"
];
-
-
extra-trusted-substituters = extra-substituters;
extra-trusted-public-keys = [
"gensokyo-global:XiCN0D2XeSxF4urFYTprR+1Nr/5hWyydcETwZtPG6Ec="
···
url = "github:zhaofengli/attic";
inputs.nixpkgs.follows = "nixpkgs";
};
mystia = {
url = "github:soopyc/mystia";
inputs.nixpkgs.follows = "nixpkgs";
};
};
-
outputs = { nixpkgs, home-manager, ... }@inputs:
-
let
-
# pkgs = import nixpkgs {};
-
_utils = import ./global/utils.nix {};
lib = nixpkgs.lib;
in {
nixosConfigurations = {
-
koumakan = (import ./systems/koumakan { inherit _utils lib inputs; });
};
-
# formatter.x86_64-linux = pkgs.alejendra;
};
}
···
{
description = "Gensokyo system configurations";
+
nixConfig = {
extra-substituters = [
"https://nonbunary.soopy.moe/gensokyo-global"
"https://nonbunary.soopy.moe/gensokyo-systems"
];
extra-trusted-public-keys = [
"gensokyo-global:XiCN0D2XeSxF4urFYTprR+1Nr/5hWyydcETwZtPG6Ec="
···
url = "github:zhaofengli/attic";
inputs.nixpkgs.follows = "nixpkgs";
};
+
+
sops-nix = {
+
url = "github:Mic92/sops-nix";
+
inputs.nixpkgs.follows = "nixpkgs";
+
};
+
mystia = {
url = "github:soopyc/mystia";
inputs.nixpkgs.follows = "nixpkgs";
};
};
+
outputs = {
+
nixpkgs,
+
home-manager,
+
...
+
} @ inputs: let
+
utils = import ./global/utils.nix;
lib = nixpkgs.lib;
+
+
systems = [
+
"x86_64-linux"
+
"aarch64-linux"
+
"x86_64-darwin"
+
"aarch64-darwin"
+
];
+
forAllSystems = fn: lib.genAttrs systems (s: fn nixpkgs.legacyPackages.${s});
in {
nixosConfigurations = {
+
koumakan = import ./systems/koumakan {inherit utils lib inputs;};
};
+
devShells = forAllSystems (pkgs: {
+
default = pkgs.mkShell {
+
packages = [
+
(pkgs.python311.withPackages (p: [p.requests]))
+
];
+
};
+
});
+
+
formatter.x86_64-linux = nixpkgs.legacyPackages.x86_64-linux.alejandra;
};
}
+4 -8
global/core.nix
···
-
{ pkgs, ... }:
-
{
imports = [
./upgrade-diff.nix
];
# Set default i18n configuration
i18n.defaultLocale = "en_US.UTF-8";
···
keyMap = "us";
};
-
# # Enable crash dumps globally
-
# boot.crashDump = {
-
# enable = true;
-
# reservedMemory = "128M";
-
# };
# Lock root account
-
users.users.root.shell = pkgs.shadow; # basically /bin/nologin
}
···
+
{pkgs, ...}: {
imports = [
./upgrade-diff.nix
+
./system
];
# Set default i18n configuration
i18n.defaultLocale = "en_US.UTF-8";
···
keyMap = "us";
};
+
time.timeZone = "Asia/Hong_Kong";
# Lock root account
+
users.users.root.shell = pkgs.shadow; # basically /bin/nologin
}
+5
global/overlays/default.nix
···
···
+
inputs:
+
with inputs; [
+
mystia.overlays.default
+
attic.overlays.default
+
]
+1 -2
global/programs/compilers.nix
···
-
{ pkgs, ... }:
-
{
environment.systemPackages = with pkgs; [
luajit
binutils
···
+
{pkgs, ...}: {
environment.systemPackages = with pkgs; [
luajit
binutils
+1 -2
global/programs/default.nix
···
-
{ ... }:
-
{
imports = [
./nix.nix
./editors.nix
···
+
{...}: {
imports = [
./nix.nix
./editors.nix
+1 -3
global/programs/editors.nix
···
-
{ pkgs, ... }:
-
-
{
programs.neovim = {
enable = true;
defaultEditor = true;
···
+
{...}: {
programs.neovim = {
enable = true;
defaultEditor = true;
+2 -4
global/programs/gpg.nix
···
-
{ pkgs, ... }:
-
-
{
-
environment.systemPackages = with pkgs; [ gnupg pinentry ];
programs.gnupg.agent.enable = true;
# ideally this should be set automatically but in case that doesn't work
···
+
{pkgs, ...}: {
+
environment.systemPackages = with pkgs; [gnupg pinentry];
programs.gnupg.agent.enable = true;
# ideally this should be set automatically but in case that doesn't work
+2 -3
global/programs/misc.nix
···
-
{ pkgs, ... }:
-
-
{
# Miscellaneous packages that do not have an option.
# It is recommended to use packages.<package>.enable when possible.
···
nvd
just
git-crypt
];
···
+
{pkgs, ...}: {
# Miscellaneous packages that do not have an option.
# It is recommended to use packages.<package>.enable when possible.
···
nvd
just
+
attic
git-crypt
];
+1 -3
global/programs/multiplexers.nix
···
-
{ pkgs, ... }:
-
-
{
programs.tmux = {
enable = true;
newSession = true;
···
+
{pkgs, ...}: {
programs.tmux = {
enable = true;
newSession = true;
+6 -6
global/programs/nix.nix
···
-
{ pkgs, ... }:
-
# some items are sourced from https://jackson.dev/post/nix-reasonable-defaults/
{
nix.settings = {
experimental-features = [
"nix-command"
"flakes"
];
substituters = [
-
"https://nonbunary.soopy.moe/gensokyo-systems"
-
"https://nonbunary.soopy.moe/gensokyo-global"
];
trusted-substituters = [
-
"https://nonbunary.soopy.moe/gensokyo-systems"
-
"https://nonbunary.soopy.moe/gensokyo-global"
];
trusted-public-keys = [
···
+
{pkgs, ...}:
# some items are sourced from https://jackson.dev/post/nix-reasonable-defaults/
{
nix.settings = {
experimental-features = [
"nix-command"
"flakes"
+
"repl-flake"
];
substituters = [
+
"https://nonbunary.soopy.moe/gensokyo-systems/"
+
"https://nonbunary.soopy.moe/gensokyo-global/"
];
trusted-substituters = [
+
"https://nonbunary.soopy.moe/gensokyo-systems/"
+
"https://nonbunary.soopy.moe/gensokyo-global/"
];
trusted-public-keys = [
+1 -2
global/programs/scm.nix
···
-
{ ... }:
-
{
programs.git = {
enable = true;
config = {
···
+
{...}: {
programs.git = {
enable = true;
config = {
+1 -3
global/programs/shells.nix
···
-
{ pkgs, ... }:
-
-
{
users.defaultUserShell = pkgs.zsh;
programs.zsh = {
enable = true;
···
+
{pkgs, ...}: {
users.defaultUserShell = pkgs.zsh;
programs.zsh = {
enable = true;
+1 -3
global/programs/ssh.nix
···
-
{ pkgs, ... }:
-
-
{
# Enable the OpenSSH daemon.
services.openssh = {
enable = true;
···
+
{...}: {
# Enable the OpenSSH daemon.
services.openssh = {
enable = true;
+5
global/system/default.nix
···
···
+
{...}: {
+
imports = [
+
./firmware.nix
+
];
+
}
+4
global/system/firmware.nix
···
···
+
{...}: {
+
hardware.enableRedistributableFirmware = true;
+
services.fwupd.enable = true;
+
}
+1 -2
global/upgrade-diff.nix
···
# Thank you https://github.com/luishfonseca/dotfiles/blob/ab7625ec406b48493eda701911ad1cd017ce5bc1/modules/upgrade-diff.nix
-
-
{ pkgs, ... }: {
system.activationScripts.diff = {
supportsDryActivation = true;
text = ''
···
# Thank you https://github.com/luishfonseca/dotfiles/blob/ab7625ec406b48493eda701911ad1cd017ce5bc1/modules/upgrade-diff.nix
+
{pkgs, ...}: {
system.activationScripts.diff = {
supportsDryActivation = true;
text = ''
+41 -19
global/utils.nix
···
# see /docs/utils.md for a usage guide
-
-
{ ... }:
-
# let
-
# lib = pkgs.lib;
-
# in
-
rec {
-
mkVhost = opts: {
-
# ideally mkOverride/mkDefault would be used, but i have 0 idea how it works.
-
forceSSL = true;
-
useACMEHost = "global.c.soopy.moe";
-
kTLS = true;
-
} // opts;
mkSimpleProxy = {
port,
protocol ? "http",
location ? "/",
-
websockets ? false
-
}: mkVhost {
-
locations."${location}" = {
-
proxyPass = "${protocol}://localhost:${toString port}";
-
proxyWebsockets = websockets;
-
};
-
};
}
···
# see /docs/utils.md for a usage guide
+
{
+
inputs,
+
system,
+
...
+
}: let
+
lib = inputs.nixpkgs.lib;
+
in rec {
+
mkVhost = opts:
+
lib.mkMerge [
+
{
+
forceSSL = lib.mkDefault true;
+
useACMEHost = lib.mkDefault "global.c.soopy.moe";
+
kTLS = lib.mkDefault true;
+
locations."/_cgi/error/" = {
+
alias = "${inputs.mystia.packages.${system}.staticly}/nginx_error_pages/";
+
};
+
extraConfig = ''
+
error_page 503 /_cgi/error/503.html;
+
error_page 502 /_cgi/error/502.html;
+
error_page 404 /_cgi/error/404.html;
+
'';
+
}
+
opts
+
];
mkSimpleProxy = {
port,
protocol ? "http",
location ? "/",
+
websockets ? false,
+
extraConfig ? {},
+
}:
+
mkVhost (lib.mkMerge [
+
extraConfig
+
{
+
locations."${location}" = {
+
proxyPass = "${protocol}://localhost:${toString port}";
+
proxyWebsockets = websockets;
+
};
+
}
+
]);
+
+
genSecrets = namespace: files: value:
+
lib.genAttrs (
+
map (x: namespace + lib.optionalString (lib.stringLength namespace != 0) "/" + x) files
+
) (_: value);
}
+11 -4
justfile
···
# friendship ended with Makefile
# I LOVE justFILE!!!!!!
-
default: build
test:
nixos-rebuild test --flake .#
-
build:
-
nixos-rebuild build --flake .#
-
switch:
nixos-rebuild switch --flake .#
utils recipe="list":
@echo "Running utils/{{recipe}}"
@cd utils && just {{recipe}}
ebuild system:
nix build -j8 .#nixosConfigurations."{{system}}".config.system.build.toplevel
···
# friendship ended with Makefile
# I LOVE justFILE!!!!!!
+
# build the current configuration
+
build:
+
nixos-rebuild build --flake .#
+
# build and test the configuration, but don't switch
test:
nixos-rebuild test --flake .#
+
# switch to the current configuration
switch:
nixos-rebuild switch --flake .#
+
# run utility programs
utils recipe="list":
@echo "Running utils/{{recipe}}"
@cd utils && just {{recipe}}
+
# update an input in the flake lockfile
+
update-input input:
+
nix flake lock --update-input {{input}}
+
+
# build the flake on a non-nixos platform
ebuild system:
nix build -j8 .#nixosConfigurations."{{system}}".config.system.build.toplevel
-1
overlays/default.nix
···
-
[]
···
+4 -5
systems/koumakan/certificates/default.nix
···
-
{ ... }:
-
-
{
imports = [
./global.nix
./postgresql.nix
];
security.acme = {
···
# == lego Configuration ==
credentialsFile = "/etc/lego/desec";
dnsProvider = "desec";
-
# In an more ideal world we would have an eddsa algo here but oh well
-
keyType = "ec256"; # Ensure we use ec keys
dnsResolver = "8.8.8.8:53";
···
+
{...}: {
imports = [
./global.nix
./postgresql.nix
+
./fediverse.nix
];
security.acme = {
···
# == lego Configuration ==
credentialsFile = "/etc/lego/desec";
dnsProvider = "desec";
+
# In a more ideal world we would have an eddsa algo here but oh well
+
keyType = "ec256"; # Ensure we use ec keys
dnsResolver = "8.8.8.8:53";
+11
systems/koumakan/certificates/fediverse.nix
···
···
+
{...}: {
+
# Certificate for fedi services
+
security.acme.certs."fedi.c.soopy.moe" = {
+
group = "nginx";
+
extraDomainNames = [
+
"a.soopy.moe"
+
"m.soopy.moe"
+
"pixie.soopy.moe"
+
];
+
};
+
}
+1 -3
systems/koumakan/certificates/global.nix
···
-
{ ... }:
-
-
{
# Global certificate
security.acme.certs."global.c.soopy.moe" = {
group = "nginx";
···
+
{...}: {
# Global certificate
security.acme.certs."global.c.soopy.moe" = {
group = "nginx";
+1 -3
systems/koumakan/certificates/postgresql.nix
···
-
{ config, ... }:
-
-
{
# PostgreSQL only certificate
security.acme.certs."phant.soopy.moe" = {
group = "postgres";
···
+
{config, ...}: {
# PostgreSQL only certificate
security.acme.certs."phant.soopy.moe" = {
group = "postgres";
+27 -36
systems/koumakan/configuration.nix
···
-
# Edit this configuration file to define what should be installed on
-
# your system. Help is available in the configuration.nix(5) man page
-
# and in the NixOS manual (accessible by running `nixos-help`).
-
-
{ inputs, ... }:
-
-
{
-
imports = [ # Include the results of the hardware scan.
-
./hardware-configuration.nix
-
../../global/core.nix
-
../../global/programs
-
./networking
-
./certificates
-
./security
-
./services
];
-
nixpkgs.overlays = import ../../overlays ++ (with inputs; [
-
mystia.overlays.default
-
attic.overlays.default
-
]);
-
boot.loader.efi = {
-
canTouchEfiVariables = true;
-
efiSysMountPoint = "/boot/efi";
};
-
boot.loader.systemd-boot = {
-
enable = true;
-
graceful = true;
-
netbootxyz.enable = true;
-
};
-
-
boot.loader.grub = {
-
enable = false;
-
};
-
-
time.timeZone = "Asia/Hong_Kong";
-
# Define a user account. Don't forget to set a password with โ€˜passwdโ€™.
users.users.cassie = {
isNormalUser = true;
-
extraGroups = [ "wheel" ];
openssh = {
-
authorizedKeys.keyFiles = [ ../../creds/ssh/cassie ];
};
# packages = with pkgs; [];
};
# Just don't change this :p
system.stateVersion = "23.05"; # Did you read the comment?
···
+
{inputs, ...}: {
+
imports = [
+
# Include the results of the hardware scan.
+
./hardware-configuration.nix
+
../../global/core.nix
+
../../global/programs
+
./networking
+
./certificates
+
./security
+
./services
];
+
nixpkgs.overlays = import ../../global/overlays inputs;
+
boot.loader = {
+
efi = {
+
canTouchEfiVariables = true;
+
efiSysMountPoint = "/boot/efi";
+
};
+
systemd-boot = {
+
enable = true;
+
graceful = true;
+
netbootxyz.enable = true;
+
};
+
grub.enable = false;
};
# Define a user account. Don't forget to set a password with โ€˜passwdโ€™.
users.users.cassie = {
isNormalUser = true;
+
extraGroups = ["wheel"];
openssh = {
+
authorizedKeys.keyFiles = [../../creds/ssh/cassie];
};
# packages = with pkgs; [];
};
+
+
sops.age.sshKeyPaths = ["/etc/ssh/ssh_host_ed25519_key"];
+
sops.defaultSopsFile = ../../creds/sops/koumakan.yaml;
# Just don't change this :p
system.stateVersion = "23.05"; # Did you read the comment?
+12 -3
systems/koumakan/default.nix
···
-
{ lib, _utils, inputs, ... }:
-
lib.nixosSystem {
system = "x86_64-linux";
# see docs/tips_n_tricks.md#extra_opts for syntax
# see docs/utils.md for functions
specialArgs = {
-
inherit inputs _utils;
};
modules = [
inputs.lanzaboote.nixosModules.lanzaboote
inputs.attic.nixosModules.atticd
./configuration.nix
];
···
+
{
+
lib,
+
utils,
+
inputs,
+
...
+
}:
lib.nixosSystem {
system = "x86_64-linux";
# see docs/tips_n_tricks.md#extra_opts for syntax
# see docs/utils.md for functions
specialArgs = {
+
inherit inputs;
+
_utils = utils {
+
inherit inputs;
+
system = "x86_64-linux";
+
};
};
modules = [
inputs.lanzaboote.nixosModules.lanzaboote
inputs.attic.nixosModules.atticd
+
inputs.sops-nix.nixosModules.sops
./configuration.nix
];
+48 -44
systems/koumakan/hardware-configuration.nix
···
# Do not modify this file! It was generated by โ€˜nixos-generate-configโ€™
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
-
{ config, lib, pkgs, modulesPath, ... }:
-
{
-
imports =
-
[ (modulesPath + "/installer/scan/not-detected.nix")
-
];
-
boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "usbhid" "sr_mod" ];
-
boot.initrd.kernelModules = [ "dm-snapshot" ];
-
boot.kernelModules = [ "kvm-intel" ];
-
boot.extraModulePackages = [ ];
-
fileSystems."/" =
-
{ device = "/dev/disk/by-uuid/0b38be0c-5365-4f02-85b8-72f37bb2ddf8";
-
fsType = "btrfs";
-
};
-
fileSystems."/var/log" =
-
{ device = "/dev/disk/by-uuid/e6ff7c96-3bef-4a17-9114-64ef1460fc00";
-
fsType = "btrfs";
-
};
-
fileSystems."/var/log/audit" =
-
{ device = "/dev/disk/by-uuid/a20e2995-7297-4f69-af89-b58ff314e029";
-
fsType = "btrfs";
-
};
-
fileSystems."/srv/osm-data" =
-
{ device = "/dev/disk/by-uuid/3c1a8b58-fbe6-4522-8e27-72419b3c2d6f";
-
fsType = "btrfs";
-
};
-
fileSystems."/boot" =
-
{ device = "/dev/disk/by-uuid/9E0F-3FDE";
-
fsType = "vfat";
-
};
-
fileSystems."/boot/efi" =
-
{ device = "/dev/disk/by-uuid/9EB1-FA5A";
-
fsType = "vfat";
-
};
-
fileSystems."/srv/www/keine" =
-
{ device = "/dev/disk/by-uuid/0a0e102a-b1ac-44a2-947b-2ec505b532ad";
-
fsType = "btrfs";
-
};
-
fileSystems."/home" =
-
{ device = "/dev/disk/by-uuid/50165105-6b82-4228-9640-2d32ce45f76e";
-
fsType = "btrfs";
-
};
-
swapDevices =
-
[ { device = "/dev/disk/by-uuid/efd68464-2e0c-4aaf-8264-519dd7d05ddf"; }
-
];
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
···
# Do not modify this file! It was generated by โ€˜nixos-generate-configโ€™
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{
+
config,
+
lib,
+
pkgs,
+
modulesPath,
+
...
+
}: {
+
imports = [
+
(modulesPath + "/installer/scan/not-detected.nix")
+
];
+
boot.initrd.availableKernelModules = ["xhci_pci" "ahci" "usbhid" "sr_mod"];
+
boot.initrd.kernelModules = ["dm-snapshot"];
+
boot.kernelModules = ["kvm-intel"];
+
boot.extraModulePackages = [];
+
fileSystems."/" = {
+
device = "/dev/disk/by-uuid/0b38be0c-5365-4f02-85b8-72f37bb2ddf8";
+
fsType = "btrfs";
+
};
+
fileSystems."/var/log" = {
+
device = "/dev/disk/by-uuid/e6ff7c96-3bef-4a17-9114-64ef1460fc00";
+
fsType = "btrfs";
+
};
+
fileSystems."/var/log/audit" = {
+
device = "/dev/disk/by-uuid/a20e2995-7297-4f69-af89-b58ff314e029";
+
fsType = "btrfs";
+
};
+
fileSystems."/srv/osm-data" = {
+
device = "/dev/disk/by-uuid/3c1a8b58-fbe6-4522-8e27-72419b3c2d6f";
+
fsType = "btrfs";
+
};
+
fileSystems."/boot" = {
+
device = "/dev/disk/by-uuid/9E0F-3FDE";
+
fsType = "vfat";
+
};
+
fileSystems."/boot/efi" = {
+
device = "/dev/disk/by-uuid/9EB1-FA5A";
+
fsType = "vfat";
+
};
+
fileSystems."/srv/www/keine" = {
+
device = "/dev/disk/by-uuid/0a0e102a-b1ac-44a2-947b-2ec505b532ad";
+
fsType = "btrfs";
+
};
+
fileSystems."/home" = {
+
device = "/dev/disk/by-uuid/50165105-6b82-4228-9640-2d32ce45f76e";
+
fsType = "btrfs";
+
};
+
swapDevices = [
+
{device = "/dev/disk/by-uuid/efd68464-2e0c-4aaf-8264-519dd7d05ddf";}
+
];
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's
+1 -3
systems/koumakan/networking/default.nix
···
-
{ ... }:
-
-
{
imports = [
./firewall.nix
./interface.nix
···
+
{...}: {
imports = [
./firewall.nix
./interface.nix
+3 -4
systems/koumakan/networking/firewall.nix
···
-
{ pkgs, ... }:
-
-
{
networking.firewall = {
enable = true;
allowedTCPPorts = [
22 # ssh
-
80 443 # http[s]
];
};
}
···
+
{...}: {
networking.firewall = {
enable = true;
allowedTCPPorts = [
22 # ssh
+
80
+
443 # http[s]
];
};
}
+2 -3
systems/koumakan/networking/interface.nix
···
-
{ ... } :
-
{
-
networking.networkmanager.ethernet.macAddress = builtins.readFile ./nma.cry;
}
···
+
{...}: {
+
networking.networkmanager.ethernet.macAddress = "stable";
}
systems/koumakan/networking/nma.cry

This is a binary file and will not be displayed.

+1 -2
systems/koumakan/security/default.nix
···
-
{ ... }:
-
{
imports = [
./pam.nix
./sudo.nix
···
+
{...}: {
imports = [
./pam.nix
./sudo.nix
+2 -3
systems/koumakan/security/pam.nix
···
-
{ ... }:
-
{
security.pam.yubico = {
enable = true;
-
id = builtins.readFile ./ykid.cry;
mode = "client";
control = "requisite";
};
···
+
{...}: {
security.pam.yubico = {
enable = true;
+
id = "91582";
mode = "client";
control = "requisite";
};
+4 -2
systems/koumakan/security/secureboot.nix
···
-
{ pkgs, lib, ... }:
-
{
environment.systemPackages = with pkgs; [
cryptsetup
sbctl
···
{
+
pkgs,
+
lib,
+
...
+
}: {
environment.systemPackages = with pkgs; [
cryptsetup
sbctl
+2 -3
systems/koumakan/security/sudo.nix
···
-
{ pkgs, ... }:
-
{
security.sudo.extraConfig = ''
Defaults insults
'';
-
security.sudo.package = (pkgs.sudo.override {withInsults = true;});
}
···
+
{pkgs, ...}: {
security.sudo.extraConfig = ''
Defaults insults
'';
+
security.sudo.package = pkgs.sudo.override {withInsults = true;};
}
systems/koumakan/security/ykid.cry

This is a binary file and will not be displayed.

+13 -10
systems/koumakan/services/attic.nix
···
-
{ _utils, pkgs, ... }:
-
-
let
# where tf are the docs for pkgs.formats??
toml = pkgs.formats.toml {};
in {
···
services.nginx.virtualHosts."nonbunary.soopy.moe" = _utils.mkSimpleProxy {
port = 38191;
-
} // {
-
extraConfig = ''
-
client_max_body_size 1G;
-
proxy_read_timeout 3h;
-
proxy_connect_timeout 3h;
-
proxy_send_timeout 3h;
-
'';
};
}
···
+
{
+
_utils,
+
pkgs,
+
...
+
}: let
# where tf are the docs for pkgs.formats??
toml = pkgs.formats.toml {};
in {
···
services.nginx.virtualHosts."nonbunary.soopy.moe" = _utils.mkSimpleProxy {
port = 38191;
+
extraConfig = {
+
extraConfig = ''
+
client_max_body_size 1G;
+
proxy_read_timeout 3h;
+
proxy_connect_timeout 3h;
+
proxy_send_timeout 3h;
+
'';
+
};
};
}
+6
systems/koumakan/services/databases/default.nix
···
···
+
{...}: {
+
imports = [
+
./postgresql.nix
+
./redis.nix
+
];
+
}
+40
systems/koumakan/services/databases/postgresql.nix
···
···
+
{pkgs, ...}: {
+
services.postgresql = {
+
enable = true;
+
+
package = pkgs.postgresql_15;
+
dataDir = "/var/lib/postgresql/15";
+
logLinePrefix = "%m [%p] %h ";
+
+
authentication = ''
+
# unix socket connection
+
local all all peer
+
# local ipv4/6 tcp connection
+
host all all 127.0.0.1/32 scram-sha-256
+
host all all ::1/128 scram-sha-256
+
# world (encrypted) tcp traffic
+
hostssl all all all scram-sha-256
+
'';
+
+
settings = let
+
credsDir = "/run/credentials/postgresql.service";
+
in {
+
listen_addresses = pkgs.lib.mkForce "*";
+
max_connections = 200;
+
password_encryption = "scram-sha-256";
+
+
ssl = "on";
+
ssl_cert_file = "${credsDir}/cert.pem";
+
ssl_key_file = "${credsDir}/key.pem";
+
+
log_hostname = true;
+
datestyle = "iso, dmy";
+
log_timezone = "Asia/Hong_Kong";
+
timezone = "Asia/Hong_Kong";
+
default_text_search_config = "pc_catalog.english";
+
+
max_wal_size = "2GB";
+
min_wal_size = "80MB";
+
};
+
};
+
}
+5
systems/koumakan/services/databases/redis.nix
···
···
+
{...}: {
+
services.redis.servers."" = {
+
enable = true;
+
};
+
}
+6 -6
systems/koumakan/services/default.nix
···
-
{ ... }:
-
-
{
imports = [
./nginx.nix
-
# databases
-
./postgresql.nix
-
./redis.nix
./attic.nix
./proxies
./static-sites
···
+
{...}: {
imports = [
./nginx.nix
+
./databases
./attic.nix
+
+
# fediverse
+
./matrix
+
./fediverse
./proxies
./static-sites
+150
systems/koumakan/services/fediverse/akkoma.nix
···
···
+
{
+
_utils,
+
pkgs,
+
config,
+
lib,
+
...
+
}: let
+
mkRaw = (pkgs.formats.elixirConf {}).lib.mkRaw;
+
# I don't know what i did but i made this abomination
+
mkSecret = file:
+
if !lib.elem file secrets
+
then throw "Provided secret file ${file} is not in the list of defined secrets."
+
else {_secret = "/run/secrets/akkoma/${file}";};
+
secrets = [
+
"joken_default_signer" # can't think of any better name spacing
+
"dist/cookie"
+
"search/meili/host_unencrypted"
+
"search/meili/key"
+
"endpoint/secret_base"
+
"endpoint/salt"
+
"endpoint/live_view/salt"
+
"vapid/pub"
+
"vapid/key"
+
"postgres/hostname"
+
"postgres/database_unencrypted"
+
"postgres/username"
+
"postgres/password"
+
"smtp/username"
+
"smtp/password"
+
"smtp/relay"
+
];
+
in {
+
# secrets definition
+
sops.secrets = _utils.genSecrets "akkoma" secrets {};
+
+
services.akkoma = {
+
enable = true;
+
initSecrets = false;
+
initDb.enable = false;
+
# TODO: figure out how to add swagger ui
+
# frontends = {
+
# swagger
+
# };
+
+
# TODO: Issue #5
+
dist.cookie = mkSecret "dist/cookie";
+
config = {
+
":joken".":default_signer" = mkSecret "joken_default_signer";
+
+
":pleroma" = {
+
":http_security" = {
+
sts = true;
+
};
+
+
":configurable_from_database" = true;
+
":instance" = {
+
name = "CassieAkko";
+
description = "You should not see this here...";
+
email = "me@soopy.moe";
+
notify_email = "noreply@a.soopy.moe";
+
limit = 5000;
+
registrations_open = true;
+
};
+
+
# TODO: add proper proxy support
+
# also refer to https://meta.akkoma.dev/t/another-vector-for-the-injection-vulnerability-found/483
+
":media_proxy" = {
+
enabled = true;
+
redirect_on_failure = true;
+
};
+
+
"Pleroma.Repo" = {
+
adapter = mkRaw "Ecto.Adapters.Postgres";
+
database = mkSecret "postgres/database_unencrypted";
+
hostname = mkSecret "postgres/hostname";
+
username = mkSecret "postgres/username";
+
password = mkSecret "postgres/password";
+
};
+
+
"Pleroma.Upload" = {
+
filters = [
+
(mkRaw "Pleroma.Upload.Filter.Exiftool")
+
(mkRaw "Pleroma.Upload.Filter.Dedupe")
+
];
+
};
+
+
"Pleroma.Web.Endpoint" = {
+
# We don't need to specify http ip/ports here because we use unix sockets
+
# ok we do because it's broken
+
http = {
+
ip = "127.0.0.1";
+
port = 35378;
+
};
+
url = {
+
host = "a.soopy.moe";
+
scheme = "https";
+
port = 443;
+
};
+
secure_cookie_flag = true;
+
+
secret_key_base = mkSecret "endpoint/secret_base";
+
signing_salt = mkSecret "endpoint/salt";
+
live_view = {
+
signing_salt = mkSecret "endpoint/live_view/salt";
+
};
+
};
+
+
"Pleroma.Emails.Mailer" = {
+
adapter = mkRaw "Swoosh.Adapters.SMTP";
+
relay = mkSecret "smtp/relay";
+
username = mkSecret "smtp/username";
+
password = mkSecret "smtp/password";
+
};
+
+
"Pleroma.Search.Meilisearch" = {
+
url = mkSecret "search/meili/host_unencrypted";
+
private_key = mkSecret "search/meili/key";
+
initial_indexing_chunk_size = 100000;
+
};
+
};
+
+
":web_push_encryption".":vapid_details" = {
+
subject = "mailto:me@soopy.moe";
+
public_key = mkSecret "vapid/pub";
+
private_key = mkSecret "vapid/key";
+
};
+
};
+
+
nginx = _utils.mkVhost {
+
useACMEHost = "fedi.c.soopy.moe";
+
extraConfig = ''
+
client_max_body_size 100M;
+
'';
+
};
+
+
extraStatic = {
+
"static/terms-of-service.html" = pkgs.writeText "terms-of-service.html" ''
+
<h1>Terms of Service</h1><p>Please refer to this ToS:
+
<a href="https://m.soopy.moe/@admin/pages/tos" rel="noopener noreferrer nofollow">
+
https://m.soopy.moe/@admin/pages/tos</a></p>
+
'';
+
# refer to https://github.com/NixOS/nixpkgs/blob/nixos-unstable/pkgs/servers/akkoma/emoji/blobs_gg.nix#L29
+
# "emoji/Cat_girls_Emoji" = ...
+
};
+
};
+
+
systemd.services.akkoma-config = {
+
serviceConfig.SupplementaryGroups = [config.users.groups.keys.name];
+
};
+
}
+5
systems/koumakan/services/fediverse/default.nix
···
···
+
{...}: {
+
imports = [
+
./akkoma.nix
+
];
+
}
+5
systems/koumakan/services/matrix/default.nix
···
···
+
{...}: {
+
imports = [
+
./synapse.nix
+
];
+
}
+116
systems/koumakan/services/matrix/synapse.nix
···
···
+
{
+
_utils,
+
pkgs,
+
config,
+
...
+
}: {
+
sops.secrets."synapse.yaml" = {
+
mode = "0400";
+
owner = config.users.users.matrix-synapse.name;
+
};
+
+
sops.secrets.matrix-signing-key = {
+
mode = "0400";
+
owner = config.users.users.matrix-synapse.name;
+
};
+
+
users.users.matrix-synapse.extraGroups = [config.users.groups.keys.name];
+
+
services.matrix-synapse = {
+
enable = true;
+
withJemalloc = true;
+
extras = [
+
"jwt"
+
"oidc"
+
];
+
+
extraConfigFiles = [
+
"/run/secrets/synapse.yaml"
+
];
+
+
settings = {
+
server_name = "nue.soopy.moe";
+
serve_server_wellknown = true;
+
allow_public_rooms_over_federation = true;
+
federation_client_minimum_tls_version = 1.2;
+
# TODO: Setup TURN servers
+
# TODO: Setup OIDC providers
+
# TODO: Configure email
+
# TODO: Setup opentracing
+
url_preview_enabled = true;
+
enable_registration = false;
+
session_lifetime = "99y";
+
+
max_upload_size = "100M";
+
signing_key_path = "/run/secrets/matrix-signing-key";
+
+
server_notices = {
+
system_mxid_localpart = "server";
+
system_mxid_display_name = "Server Notices";
+
room_name = "Server Notices";
+
};
+
+
trusted_key_servers = [
+
{
+
server_name = "matrix.org";
+
verify_keys = {
+
"ed25519:auto" = "Noi6WqcDj0QmPxCNQqgezwTlBKrfqehY1u2FyWP9uYw";
+
};
+
}
+
{
+
server_name = "m.lea.moe";
+
}
+
];
+
+
password_config = {
+
policy = {
+
enabled = true;
+
minimum_length = 12;
+
};
+
};
+
};
+
};
+
+
services.postgresql = {
+
ensureDatabases = ["synapse"];
+
ensureUsers = [
+
{
+
name = "synapse";
+
ensurePermissions = {
+
"database \"synapse\"" = "all privileges";
+
};
+
}
+
];
+
};
+
+
services.nginx.virtualHosts."nue.soopy.moe" = _utils.mkVhost {
+
locations."= /config.json" = {
+
alias = "${pkgs.staticly}/configs/";
+
tryFiles = "cinny.json =404";
+
extraConfig = ''
+
add_header access_control_allow_origin "*";
+
'';
+
};
+
+
locations."= /.well-known/matrix/server" = {
+
return = "200 '{\"m.server\": \"nue.soopy.moe:443\"}'";
+
};
+
+
locations."~ ^(/_matrix|/_synapse/client)" = {
+
proxyPass = "http://localhost:8008";
+
extraConfig = ''
+
client_max_body_size 100M;
+
'';
+
};
+
+
locations."= /.well-known/matrix/client" = {
+
alias = "${pkgs.staticly}/configs/matrix/";
+
tryFiles = "stable.json =404";
+
};
+
+
locations."/" = {
+
root = "${pkgs.staticly}/pages/matrix/landing/";
+
tryFiles = "$uri $uri/index.html $uri.html =404";
+
};
+
};
+
}
+1 -3
systems/koumakan/services/nginx.nix
···
-
{ pkgs, ... }:
-
-
{
services.nginx = {
enable = true;
enableReload = true;
···
+
{pkgs, ...}: {
services.nginx = {
enable = true;
enableReload = true;
-42
systems/koumakan/services/postgresql.nix
···
-
{ pkgs, ... }:
-
-
{
-
services.postgresql = {
-
enable = true;
-
-
package = pkgs.postgresql_15;
-
dataDir = "/var/lib/postgresql/15";
-
logLinePrefix = "%m [%p] %h "; # bollocks to that
-
-
authentication = ''
-
# unix socket connection
-
local all all trust
-
# local ipv4/6 tcp connection
-
host all all 127.0.0.1/32 scram-sha-256
-
host all all ::1/128 scram-sha-256
-
# world (encrypted) tcp traffic
-
hostssl all all all scram-sha-256
-
'';
-
-
settings = let
-
credsDir = "/run/credentials/postgresql.service";
-
in {
-
listen_addresses = pkgs.lib.mkForce "*";
-
max_connections = 200;
-
password_encryption = "scram-sha-256";
-
-
ssl = "on";
-
ssl_cert_file = "${credsDir}/cert.pem";
-
ssl_key_file = "${credsDir}/key.pem";
-
-
log_hostname = true;
-
datestyle = "iso, dmy";
-
log_timezone = "Asia/Hong_Kong";
-
timezone = "Asia/Hong_Kong";
-
default_text_search_config = "pc_catalog.english";
-
-
max_wal_size = "2GB";
-
min_wal_size = "80MB";
-
};
-
};
-
}
···
+1 -3
systems/koumakan/services/proxies/default.nix
···
-
{ ... }:
-
-
{
imports = [
./nitter.nix
];
···
+
{...}: {
imports = [
./nitter.nix
];
+5 -3
systems/koumakan/services/proxies/nitter.nix
···
-
{ _utils, pkgs, ... }:
-
{
services.nitter = {
enable = true;
-
redisCreateLocally = false; # why is the default of this `true`??
server = {
title = "NSM";
port = 36325;
···
{
+
_utils,
+
pkgs,
+
...
+
}: {
services.nitter = {
enable = true;
+
redisCreateLocally = false; # why is the default of this `true`??
server = {
title = "NSM";
port = 36325;
-6
systems/koumakan/services/redis.nix
···
-
{ ... }:
-
{
-
services.redis.servers."" = {
-
enable = true;
-
};
-
}
···
+2 -4
systems/koumakan/services/static-sites/default.nix
···
-
{ ... }:
-
{
imports = [
./keine.nix
];
···
"~ ^/(index.html|splash.png)".root = "/srv/www/maintenance";
};
extraConfig = ''
-
error_page 503 /index.html;
'';
-
};
}
···
+
{...}: {
imports = [
./keine.nix
];
···
"~ ^/(index.html|splash.png)".root = "/srv/www/maintenance";
};
extraConfig = ''
+
error_page 503 /index.html;
'';
};
}
+4 -5
systems/koumakan/services/static-sites/keine.nix
···
-
{ ... }:
-
{
-
services.nginx.virtualHosts."keine.soopy.moe" = {
-
useACMEHost = "global.c.soopy.moe";
-
addSSL = true; # Don't force SSL on a mirror (implications TBD)
root = "/srv/www/keine";
locations = {
···
+
{_utils, ...}: {
+
services.nginx.virtualHosts."keine.soopy.moe" = _utils.mkVhost {
+
forceSSL = false;
+
addSSL = true; # Don't force SSL on a mirror (implications TBD)
root = "/srv/www/keine";
locations = {
-59
utils/flake.lock
···
-
{
-
"nodes": {
-
"flake-utils": {
-
"inputs": {
-
"systems": "systems"
-
},
-
"locked": {
-
"lastModified": 1692799911,
-
"narHash": "sha256-3eihraek4qL744EvQXsK1Ha6C3CR7nnT8X2qWap4RNk=",
-
"owner": "numtide",
-
"repo": "flake-utils",
-
"rev": "f9e7cf818399d17d347f847525c5a5a8032e4e44",
-
"type": "github"
-
},
-
"original": {
-
"owner": "numtide",
-
"repo": "flake-utils",
-
"type": "github"
-
}
-
},
-
"nixpkgs": {
-
"locked": {
-
"lastModified": 1693060755,
-
"narHash": "sha256-KNsbfqewEziFJEpPR0qvVz4rx0x6QXxw1CcunRhlFdk=",
-
"owner": "NixOS",
-
"repo": "nixpkgs",
-
"rev": "c66ccfa00c643751da2fd9290e096ceaa30493fc",
-
"type": "github"
-
},
-
"original": {
-
"id": "nixpkgs",
-
"type": "indirect"
-
}
-
},
-
"root": {
-
"inputs": {
-
"flake-utils": "flake-utils",
-
"nixpkgs": "nixpkgs"
-
}
-
},
-
"systems": {
-
"locked": {
-
"lastModified": 1681028828,
-
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
-
"owner": "nix-systems",
-
"repo": "default",
-
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
-
"type": "github"
-
},
-
"original": {
-
"owner": "nix-systems",
-
"repo": "default",
-
"type": "github"
-
}
-
}
-
},
-
"root": "root",
-
"version": 7
-
}
···
-16
utils/flake.nix
···
-
{
-
inputs = {
-
flake-utils.url = "github:numtide/flake-utils";
-
};
-
-
outputs = { self, nixpkgs, flake-utils }:
-
flake-utils.lib.eachDefaultSystem (system:
-
let
-
pkgs = nixpkgs.legacyPackages.${system};
-
in {
-
packages = rec {
-
python3 = pkgs.python311.withPackages (p: with p; [requests]);
-
default = python3;
-
};
-
});
-
}
···
+2 -1
utils/justfile
···
-
python_executable := if os() == "android" { "python3" } else { "nix run .#python3 --" }
list:
just -l
nitter-token:
{{python_executable}} nitter-guest-account.py tokens.json
···
+
python_executable := if os() == "android" { "python3" } else { "nix develop ..# -c python3" }
list:
just -l
+
# grab a new nitter guest account and save it
nitter-token:
{{python_executable}} nitter-guest-account.py tokens.json
-146
utils/nitter-guest-account.js
···
-
// adapted from https://github.com/zedeus/nitter/issues/983#issuecomment-1681199357
-
// deno run --allow-{env,read,net} nitter-guest-account.js
-
-
import axios from 'npm:axios'
-
import chalk from 'npm:chalk'
-
const TW_CONSUMER_KEY = '3nVuSoBZnx6U4vzUxf5w'
-
const TW_CONSUMER_SECRET = 'Bcs59EFbbsdF6Sl9Ng71smgStWEGwXXKSjYvPVt7qys'
-
-
const TW_ANDROID_BASIC_TOKEN = `Basic ${btoa(TW_CONSUMER_KEY+':'+TW_CONSUMER_SECRET)}`
-
-
const VERBOSE_MODE = Deno.args.includes('-v') || Deno.args.includes("--verbose") || Deno.args.includes('--debug') || Deno.args.includes('-d')
-
const NO_PRETTYPRINT = Deno.args.includes('-P') || Deno.args.includes("--no-pretty")
-
-
function debug(msg) {
-
if (VERBOSE_MODE) {
-
console.log(chalk.gray(`[*] ${msg}`))
-
}
-
}
-
-
const getBearerToken = async () => {
-
console.error(chalk.blue("[i] Getting bearer token..."));
-
const tmpTokenResponse = await axios('https://api.twitter.com/oauth2/token', {
-
headers: {
-
Authorization: TW_ANDROID_BASIC_TOKEN,
-
'Content-Type': 'application/x-www-form-urlencoded'
-
},
-
method: 'post',
-
data: 'grant_type=client_credentials'
-
});
-
return Object.values(tmpTokenResponse.data).join(" ");
-
}
-
// The bearer token is immutable
-
// Bearer AAAAAAAAAAAAAAAAAAAAAFXzAwAAAAAAMHCxpeSDG1gLNLghVe8d74hl6k4%3DRUMF4xAQLsbeBhTSRrCiQpJtxoGWeyHrDb5te2jpGskWDFW82F
-
const bearer_token = await getBearerToken()
-
console.error(chalk.blue(`[i] bearer token = ${bearer_token}`));
-
if (bearer_token.toLowerCase() !== "Bearer AAAAAAAAAAAAAAAAAAAAAFXzAwAAAAAAMHCxpeSDG1gLNLghVe8d74hl6k4%3DRUMF4xAQLsbeBhTSRrCiQpJtxoGWeyHrDb5te2jpGskWDFW82F".toLowerCase()) {
-
console.warn(chalk.yellow("[!] bearer token does not match expected value"))
-
} else {
-
console.error(chalk.green('[i] bearer token matches expected value'))
-
}
-
-
console.error(chalk.blue(`[i] getting guest token`))
-
const guest_token = (await axios("https://api.twitter.com/1.1/guest/activate.json", {
-
headers: {
-
Authorization: bearer_token
-
},
-
method: "post"
-
})).data.guest_token
-
console.error(chalk.blue(`[i] guest token = ${guest_token}`));
-
-
console.error(chalk.blue(`[i] getting flow_token`))
-
const flow_token_r = (await axios('https://api.twitter.com/1.1/onboarding/task.json?flow_name=welcome&api_version=1&known_device_token=&sim_country_code=us', {
-
headers: {
-
Authorization: bearer_token,
-
'Content-Type': 'application/json',
-
'User-Agent': 'TwitterAndroid/9.95.0-release.0 (29950000-r-0) ONEPLUS+A3010/9 (OnePlus;ONEPLUS+A3010;OnePlus;OnePlus3;0;;1;2016)',
-
'X-Twitter-API-Version': 5,
-
'X-Twitter-Client': 'TwitterAndroid',
-
'X-Twitter-Client-Version': '9.95.0-release.0',
-
'OS-Version': '28',
-
'System-User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 9; ONEPLUS A3010 Build/PKQ1.181203.001)',
-
'X-Twitter-Active-User': 'yes',
-
'X-Guest-Token': guest_token
-
},
-
method: 'post',
-
data: '{"flow_token":null,"input_flow_data":{"country_code":null,"flow_context":{"start_location":{"location":"splash_screen"}},"requested_variant":null,"target_user_id":0},"subtask_versions":{"generic_urt":3,"standard":1,"open_home_timeline":1,"app_locale_update":1,"enter_date":1,"email_verification":3,"enter_password":5,"enter_text":5,"one_tap":2,"cta":7,"single_sign_on":1,"fetch_persisted_data":1,"enter_username":3,"web_modal":2,"fetch_temporary_password":1,"menu_dialog":1,"sign_up_review":5,"interest_picker":4,"user_recommendations_urt":3,"in_app_notification":1,"sign_up":2,"typeahead_search":1,"user_recommendations_list":4,"cta_inline":1,"contacts_live_sync_permission_prompt":3,"choice_selection":5,"js_instrumentation":1,"alert_dialog_suppress_client_events":1,"privacy_options":1,"topics_selector":1,"wait_spinner":3,"tweet_selection_urt":1,"end_flow":1,"settings_list":7,"open_external_link":1,"phone_verification":5,"security_key":3,"select_banner":2,"upload_media":1,"web":2,"alert_dialog":1,"open_account":2,"action_list":2,"enter_phone":2,"open_link":1,"show_code":1,"update_users":1,"check_logged_in_account":1,"enter_email":2,"select_avatar":4,"location_permission_prompt":2,"notifications_permission_prompt":4}}'
-
})).data
-
const flow_token = flow_token_r.flow_token
-
debug(`flow_token => ${JSON.stringify(flow_token_r, null, 2)}`)
-
console.error(chalk.blue(`[i] flow_token = ${flow_token}`))
-
-
const tasks_raw = (await axios('https://api.twitter.com/1.1/onboarding/task.json', {
-
headers: {
-
Authorization: bearer_token,
-
'Content-Type': 'application/json',
-
'User-Agent': 'TwitterAndroid/9.95.0-release.0 (29950000-r-0) ONEPLUS+A3010/9 (OnePlus;ONEPLUS+A3010;OnePlus;OnePlus3;0;;1;2016)',
-
'X-Twitter-API-Version': 5,
-
'X-Twitter-Client': 'TwitterAndroid',
-
'X-Twitter-Client-Version': '9.95.0-release.0',
-
'OS-Version': '28',
-
'System-User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 9; ONEPLUS A3010 Build/PKQ1.181203.001)',
-
'X-Twitter-Active-User': 'yes',
-
'X-Guest-Token': guest_token
-
},
-
method: 'post',
-
data: '{"flow_token":"' + flow_token + '","subtask_inputs":[{"open_link":{"link":"next_link"},"subtask_id":"NextTaskOpenLink"}],"subtask_versions":{"generic_urt":3,"standard":1,"open_home_timeline":1,"app_locale_update":1,"enter_date":1,"email_verification":3,"enter_password":5,"enter_text":5,"one_tap":2,"cta":7,"single_sign_on":1,"fetch_persisted_data":1,"enter_username":3,"web_modal":2,"fetch_temporary_password":1,"menu_dialog":1,"sign_up_review":5,"interest_picker":4,"user_recommendations_urt":3,"in_app_notification":1,"sign_up":2,"typeahead_search":1,"user_recommendations_list":4,"cta_inline":1,"contacts_live_sync_permission_prompt":3,"choice_selection":5,"js_instrumentation":1,"alert_dialog_suppress_client_events":1,"privacy_options":1,"topics_selector":1,"wait_spinner":3,"tweet_selection_urt":1,"end_flow":1,"settings_list":7,"open_external_link":1,"phone_verification":5,"security_key":3,"select_banner":2,"upload_media":1,"web":2,"alert_dialog":1,"open_account":2,"action_list":2,"enter_phone":2,"open_link":1,"show_code":1,"update_users":1,"check_logged_in_account":1,"enter_email":2,"select_avatar":4,"location_permission_prompt":2,"notifications_permission_prompt":4}}'
-
})).data
-
-
debug(`tasks => ${JSON.stringify(tasks_raw, null, 2)}`);
-
const subtasks = tasks_raw.subtasks;
-
const account = subtasks.find(task => task.subtask_id === 'OpenAccount')?.open_account
-
-
async function tryAppendJSON(file, content) {
-
-
async function tryRead(file, _default = "[]") {
-
try {
-
const rawD = await Deno.readTextFile(file);
-
return rawD
-
} catch (e) {
-
if (e?.code === "ENOENT") {
-
return _default
-
} else {
-
throw e
-
}
-
}
-
}
-
-
if (file) {
-
debug(`attempting to write to file ${file}`)
-
try {
-
const rD = await tryRead(file)
-
debug("read old file with contents => " + rD);
-
const oldData = JSON.parse(rD)
-
if (!Array.isArray(oldData)) {
-
console.error(chalk.red(`[!] top-level object of existing file ${file} is not an array, not proceeding.`))
-
return false;
-
}
-
oldData.push(content)
-
await Deno.writeTextFile(file, JSON.stringify(oldData, null, 4))
-
return true
-
} catch (e) {
-
console.error(chalk.red("[!] Uncaught error", e))
-
return false
-
}
-
} else {
-
debug("file is not truthy, bailing")
-
return false
-
}
-
}
-
-
if (!account) {
-
console.error(chalk.red(`[!] unable to acquire account token. API response => ${JSON.stringify(account)}`))
-
console.error(chalk.red(`[!] this might be because of a plethora of reasons, but most likely it's due to your IP being rate-limited.`))
-
console.error(chalk.red(`[!] try again with a new IP address or retry in a day.`))
-
console.info(chalk.yellow(`[i] not writing to file because we did not receive a valid account object.`))
-
} else {
-
const outfile = Deno.args.find(i => i.match(/^(?!-).*$/));
-
if (!await tryAppendJSON(outfile, account)) {
-
debug("appending to file failed, printing to stdout instead.")
-
if (NO_PRETTYPRINT) {
-
console.log(JSON.stringify(account))
-
} else {
-
console.log(account)
-
}
-
}
-
}
···
+78 -64
utils/nitter-guest-account.py
···
# thank you!
import sys
import json
import typing
import traceback
from base64 import b64encode
···
success(f'flow token => {flow_token}')
info('Fetching final account object...')
-
tasks = send_req('post', TASKS_ENDPOINT, headers=request_headers, json=get_tasks_body(flow_token)).json()
-
try:
try:
-
open_account_task = next(filter(lambda i: i.get('subtask_id') == "OpenAccount", tasks['subtasks']))
-
account = open_account_task['open_account']
-
except StopIteration:
-
debug("resulting tasks =>", format_json(tasks), override=True)
-
error("Unable to acquire guest account credentials as it isn't present in the API response.")
-
error("This might be because of a wide variety of reasons, but it most likely is due to your IP being rate-limited.")
-
error("Try again with a new IP address or in 24 hours after this attempt.")
-
return 1
-
if args.outfile == "-":
-
debug("outfile is `-`, printing to stdout")
-
print(format_json(account))
-
return 0
-
# Sanity checks
-
try:
-
debug(f"attempting to read file: {args.outfile}")
-
with open(args.outfile) as f:
-
old_data = json.load(f)
-
except FileNotFoundError:
-
# that's okay, we might be able to create it later.
-
old_data = []
-
except PermissionError:
-
# that's not okay. we will need to access the file later anyways.
-
error("unable to read file due to a permission error.")
-
error("please make sure this script has read and write access to the file.")
-
print(format_json(account))
-
return 1
-
except json.JSONDecodeError:
-
error("could not parse the provided JSON file.")
-
if not prompt_bool("Do you want to overwrite the file?", default=None):
-
warn("Not overwriting file, printing to stdout instead.")
print(format_json(account))
return 1
-
debug('assuming old data is an empty array because we are overwriting')
-
old_data = []
-
if type(old_data) != list:
-
error("top-level object of the existing JSON file is not a list.")
-
error("due to the implementation, the file must be overwritten.")
-
if not (prompt_bool("Do you want to overwrite?", default=None)):
-
warn("Not overwriting existing data, printing to stdout instead.")
print(format_json(account))
return 1
-
debug("assuming old data is an empty array because we are overwriting")
-
old_data = []
-
-
old_data.append(account)
-
try:
-
debug("attempting to write file")
-
with open(args.outfile, 'w+') as f:
-
f.write(format_json(old_data))
-
success(f"successfully written to file {args.outfile}")
-
return 0
-
except PermissionError:
-
error("unable to write to file due to permission error.")
-
error("please make sure this script has write access to the file.")
-
print(format_json(account))
-
return 1
-
except Exception as e:
-
error("Unable to write to file due to an uncaught error:", e)
-
tb = ''.join(traceback.TracebackException.from_exception(e).format())
-
debug("exception stacktrace\n" + tb)
-
print(format_json(account))
-
except Exception:
-
debug("resulting tasks =>", format_json(tasks), override=True)
-
error("an unhandled error occurred. the tasks object is printed to avoid losing otherwise successful data.")
-
error("please file a bug report and attach the traceback below.")
-
raise
return 0
···
# thank you!
import sys
import json
+
import time
+
import random
import typing
import traceback
from base64 import b64encode
···
success(f'flow token => {flow_token}')
info('Fetching final account object...')
+
backoff_time = 0
+
exception = None
+
for attempt in range(0, 6):
+
debug(f"Attempt #{attempt + 1}")
+
tasks = send_req('post', TASKS_ENDPOINT, headers=request_headers, json=get_tasks_body(flow_token)).json()
try:
+
try:
+
open_account_task = next(filter(lambda i: i.get('subtask_id') == "OpenAccount", tasks['subtasks']))
+
account = open_account_task['open_account']
+
except StopIteration as e:
+
backoff_time += random.randint(5000,10000) / 1000
+
exception = e
+
warn(f"attempt #{attempt + 1} failed to acquire token, retrying in {backoff_time}s.")
+
time.sleep(backoff_time)
+
continue
+
info(f"Attempt #{attempt + 1} succeeded")
+
if args.outfile == "-":
+
debug("outfile is `-`, printing to stdout")
+
print(format_json(account))
+
return 0
+
# Sanity checks
+
try:
+
debug(f"attempting to read file: {args.outfile}")
+
with open(args.outfile) as f:
+
old_data = json.load(f)
+
except FileNotFoundError:
+
# that's okay, we might be able to create it later.
+
old_data = []
+
except PermissionError:
+
# that's not okay. we will need to access the file later anyways.
+
error("unable to read file due to a permission error.")
+
error("please make sure this script has read and write access to the file.")
print(format_json(account))
return 1
+
except json.JSONDecodeError:
+
error("could not parse the provided JSON file.")
+
if not prompt_bool("Do you want to overwrite the file?", default=None):
+
warn("Not overwriting file, printing to stdout instead.")
+
print(format_json(account))
+
return 1
+
debug('assuming old data is an empty array because we are overwriting')
+
old_data = []
+
if type(old_data) != list:
+
error("top-level object of the existing JSON file is not a list.")
+
error("due to the implementation, the file must be overwritten.")
+
if not (prompt_bool("Do you want to overwrite?", default=None)):
+
warn("Not overwriting existing data, printing to stdout instead.")
+
print(format_json(account))
+
return 1
+
debug("assuming old data is an empty array because we are overwriting")
+
old_data = []
+
+
old_data.append(account)
+
+
try:
+
debug("attempting to write file")
+
with open(args.outfile, 'w+') as f:
+
f.write(format_json(old_data))
+
success(f"successfully written to file {args.outfile}")
+
return 0
+
except PermissionError:
+
error("unable to write to file due to permission error.")
+
error("please make sure this script has write access to the file.")
print(format_json(account))
return 1
+
except Exception as e:
+
error("Unable to write to file due to an uncaught error:", e)
+
tb = ''.join(traceback.TracebackException.from_exception(e).format())
+
debug("exception stacktrace\n" + tb)
+
print(format_json(account))
+
except Exception:
+
debug("resulting tasks =>", format_json(tasks), override=True)
+
error("an unhandled error occurred. the tasks object is printed to avoid losing otherwise successful data.")
+
error("please file a bug report and attach the traceback below.")
+
raise
+
if exception != None:
+
debug("resulting tasks =>", format_json(tasks))
+
error("Unable to acquire guest account credentials with 5 attempts as it isn't present in any of the API responses.")
+
error("This might be because of a wide variety of reasons, but it most likely is due to your IP being rate-limited.")
+
error("Try again with a new IP address or in 24 hours after this attempt.")
+
return 1
return 0