Compare commits

..

No commits in common. "main" and "ansible" have entirely different histories.

485 changed files with 4016 additions and 12209 deletions

1
.envrc
View file

@ -1 +0,0 @@
use flake

View file

@ -1,7 +0,0 @@
on: push
jobs:
check:
runs-on: nixos
steps:
- uses: actions/checkout@v4
- run: nix develop -c just check

View file

@ -1,90 +0,0 @@
name: update-inputs
on:
schedule:
- cron: "0 6 * * 2,5" # Tue & Fri
workflow_dispatch:
jobs:
update-flake-lock:
runs-on: nixos
env:
BASE_BRANCH: main
BRANCH_PREFIX: flake-lock-update
FJ_URL: https://code.oliverdavies.uk
GIT_AUTHOR_EMAIL: flake-bot@local
GIT_AUTHOR_NAME: flake-bot
GIT_COMMITTER_EMAIL: ${{ env.GIT_AUTHOR_EMAIL }}
GIT_COMMITTER_NAME: ${{ env.GIT_AUTHOR_NAME }}
steps:
- uses: actions/checkout@v3
with: { fetch-depth: 0 }
- name: Update inputs & commit
id: bump
run: |
set -o errexit
set -o nounset
set -o pipefail
BRANCH="${BRANCH_PREFIX}-${GITHUB_RUN_ID}"
git switch -c "$BRANCH"
BEFORE=$(git rev-parse HEAD)
# Nix updates inputs and commits if needed
nix flake update --commit-lock-file
AFTER=$(git rev-parse HEAD)
if [ "$BEFORE" = "$AFTER" ]; then
echo "changed=false" >> "$GITHUB_OUTPUT"
exit 0
fi
# ── Grab commit info ────────────────────────────────────────────────
# Full message
COMMIT_RAW=$(git log -1 --pretty=%B)
# First line is the short summary; we keep lines AFTER the first blank
COMMIT_BODY=$(printf '%s\n' "$COMMIT_RAW" \
| sed '1,/^$/d' \
| sed 's/^• */* /') # nicer Markdown bullet
# Title becomes first line of the PR
COMMIT_TITLE=$(printf '%s\n' "$COMMIT_RAW" | head -n1)
# JSON-escape the body so \n etc. are valid JSON
BODY_JSON=$(printf '%s' "$COMMIT_BODY" | jq -Rs .)
echo "changed=true" >> "$GITHUB_OUTPUT"
echo "branch=$BRANCH" >> "$GITHUB_OUTPUT"
echo "title=$COMMIT_TITLE" >> "$GITHUB_OUTPUT"
echo "body_json=$BODY_JSON" >> "$GITHUB_OUTPUT"
git push -u origin "$BRANCH"
- name: Open pull-request
if: steps.bump.outputs.changed == 'true'
env:
TOKEN: ${{ secrets.FLAKE_UPDATE_PAT }}
BRANCH: ${{ steps.bump.outputs.branch }}
TITLE: ${{ steps.bump.outputs.title }}
BODY_JSON: ${{ steps.bump.outputs.body_json }}
run: |
set -o errexit
set -o nounset
OWNER="${GITHUB_REPOSITORY%%/*}"
REPO="${GITHUB_REPOSITORY#*/}"
curl -fSs -X POST "$FJ_URL/api/v1/repos/$OWNER/$REPO/pulls" \
-H "Authorization: token $TOKEN" \
--json '{
"base": "'"$BASE_BRANCH"'",
"body": '"$BODY_JSON"',
"draft": false,
"head": "'"$BRANCH"'",
"title": "'"$TITLE"'"
}'

9
.gitignore vendored
View file

@ -1,6 +1,3 @@
# Nix.
/.direnv/
/result
# Syncthing.
/.stignore
/nvim/.config/nvim/.netrwhist
/nvim/.config/nvim/plugged/
/nvim/.config/nvim/plugin/packer_compiled.lua

View file

@ -1 +0,0 @@
.git/

View file

@ -1,7 +0,0 @@
Oliver Davies <oliver@oliverdavies.uk> <339813+opdavies@users.noreply.github.com>
Oliver Davies <oliver@oliverdavies.uk> <oliver+github@oliverdavies.uk>
Oliver Davies <oliver@oliverdavies.uk> <oliver.davies@tfw.wales>
Oliver Davies <oliver@oliverdavies.uk> <oliver@microserve.io>
Oliver Davies <oliver@oliverdavies.uk> <oliver@oliverdavies.dev>
Oliver Davies <oliver@oliverdavies.uk> <opdavies@gmail.com>
Oliver Davies <oliver@oliverdavies.uk> <opdavies@noreply.code.oliverdavies.uk>

View file

@ -1,67 +0,0 @@
vim.keymap.set("n", "<leader>fn", function()
require("telescope.builtin").find_files({
cwd = "modules/home-manager/coding/neovim/config"
})
end)
require("conform").setup {
formatters_by_ft = {
lua = { "stylua" },
nix = { "nixfmt" },
},
}
require("lint").linters_by_ft = {
lua = { "luacheck" },
nix = { "nix" },
}
local lspconfig = require "lspconfig"
local capabilities = require("cmp_nvim_lsp").default_capabilities(vim.lsp.protocol.make_client_capabilities())
lspconfig.lua_ls.setup {
capabilities = capabilities,
settings = {
Lua = {
completion = {
callSnippet = "Replace",
},
diagnostics = {
globals = { "vim" },
},
runtime = {
version = "LuaJIT",
},
telemetry = {
enabled = false,
},
workspace = {
library = vim.api.nvim_get_runtime_file("", true),
},
},
},
}
lspconfig.nixd.setup {
capabilities = capabilities,
cmd = { "nixd" },
settings = {
nixd = {
nixpkgs = {
expr = "import <nixpkgs> { }",
},
formatting = {
command = "nix fmt",
},
},
},
}

View file

@ -1,3 +1,40 @@
# nix-config
# dotfiles
Originally my `dotfiles` repository, this repository contains my NixOS and Home Manager-based configurations for my personal laptop (`t480`) and home server/homelab (`nixedo`).
My personal dotfiles, originally for macOS only but currently being adapted for
use on Linux based systems (Ubuntu and Pop!_OS in particular) where needed.
The repository is powered using Ansible, with each software package and its
associated configuration within separate roles within the `roles` directory.
The `neovim` role, for example, has its own tasks in `roles/neovim/tasks/main.yaml`
and files in `roles/neovim/files`.
Files within a role are typically symlinked into their required destination
so that they will be automatically updated without needing to run the playbook
again.
For example, the files and directories within the neovim role are symlinked
into `~/.config/nvim`.
## Requirements
- [Ansible](https://www.ansible.com)
- [Git](https://git-scm.com)
## Installation
```
$ ansible-playbook main.yaml --ask-become-pass
```
## Inspiration
- [Chris Toomey](https://github.com/christoomey/dotfiles)
- [Gabe Berke-Williams](https://github.com/gabebw/dotfiles)
- [Jeff Geerling](https://github.com/geerlingguy/dotfiles)
- [Robin Malfait](https://github.com/RobinMalfait/dotfiles)
- [TJ DeVries](https://github.com/tjdevries/config_manager)
- [TheAltF4Stream](https://github.com/ALT-F4-LLC/dotfiles)
- [ThePrimeagen](https://github.com/ThePrimeagen/.dotfiles)
- [Thoughtbot](https://github.com/thoughtbot/dotfiles)
- [codico](https://github.com/codicocodes/dotfiles)

3
ansible.cfg Normal file
View file

@ -0,0 +1,3 @@
[defaults]
become = true
inventory = ./hosts.ini

BIN
bin/bin/drupalorg Executable file

Binary file not shown.

20
bin/bin/git-abort Executable file
View file

@ -0,0 +1,20 @@
#!/bin/bash
# Abort a rebase, merge, `am`, a cherry-pick or a revert, depending on the situation.
if [[ -e .git/CHERRY_PICK_HEAD ]] ; then
exec git cherry-pick --abort "$@"
elif [[ -e .git/REVERT_HEAD ]] ; then
exec git revert --abort "$@"
elif [[ -e .git/rebase-apply/applying ]] ; then
exec git am --abort "$@"
elif [[ -e .git/rebase-apply ]] ; then
exec git rebase --abort "$@"
elif [[ -e .git/rebase-merge ]] ; then
exec git rebase --abort "$@"
elif [[ -e .git/MERGE_MODE ]] ; then
exec git merge --abort "$@"
else
echo git-abort: unknown state
exit -1
fi

271
bin/bin/git-close-pull-request Executable file
View file

@ -0,0 +1,271 @@
#!/usr/bin/env php
<?php
declare(strict_types=1);
/**
* Usage: git close-pull-request -t <target>
*
* Run this from a branch which has an upstream remote branch, and an associated
* pull request.
*
* The script will merge the branch into master, push master (which will
* automatically close the pull request), and delete both the local and remote
* branches.
*
* Based on a script by @christoomey. Translated into PHP.
*/
class ClosesPullRequests
{
private $targetBranch;
private $localBranch;
private $remoteBranch;
private const RUN_TYPE_COMMAND = 'command';
private const RUN_TYPE_QUERY = 'query';
public function __construct()
{
$this->localBranch = $this->run(
'git rev-parse --abbrev-ref HEAD',
self::RUN_TYPE_QUERY
);
$this->targetBranch = $this->getTargetBranchFromArgs();
$this->remoteBranch = $this->run(
'git rev-parse --abbrev-ref --symbolic-full-name @{u}',
self::RUN_TYPE_QUERY
);
$this->remoteBranch = str_replace('origin/', '', $this->remoteBranch);
}
public function __invoke(): void
{
$this->confirmCiStatusIsPassing();
// TODO: Check that the current branch has a tracking branch.
$this->ensureWorkingDirectoryAndIndexAreClean();
$this->fetchOrigin();
$this->ensureFeatureBranchInSync();
$this->ensureTargetBranchInSync();
$this->checkoutTargetBranch();
$this->mergeLocalBranch();
$this->pushTargetBranch();
$this->deleteRemoteBranch();
$this->deleteLocalBranch();
}
private function ensureWorkingDirectoryAndIndexAreClean(): void
{
echo 'Ensuring that index and working directory are clean...' . PHP_EOL;
$isIndexClean = $this->run('git diff --cached --exit-code', self::RUN_TYPE_COMMAND);
$isWorkingDirClean = $this->run('git diff --exit-code', self::RUN_TYPE_COMMAND);
if (!$isIndexClean || !$isWorkingDirClean) {
$this->dieWithMessage('Index or working dir not clean. Aborting.');
}
}
private function getTargetBranchFromArgs(): string
{
if (!$targetBranchName = $this->getArg('t:', ['target:'])) {
$this->dieWithMessage('Invalid target branch specified. Aborting.');
}
return $targetBranchName;
}
private function confirmCiStatusIsPassing(): void
{
if ($this->isForce()) {
echo 'Forced. Skipping ci-status check...' . PHP_EOL;
return;
}
echo 'Confirming ci-status on PR is green...' . PHP_EOL;
$passedCi = $this->run('gh pr checks', self::RUN_TYPE_COMMAND);
// TODO: Check if there are no CI checks. Does this return `true` as well?
if (!$passedCi) {
$this->dieWithMessage('CI pending or failed.');
}
}
private function fetchOrigin(): void
{
print 'Fetching origin to confirm local and remote in sync...'
. PHP_EOL;
$this->run('git fetch origin', self::RUN_TYPE_COMMAND);
}
private function ensureTargetBranchInSync(): void
{
$this->ensureBranchInSyncWithUpstream(
$this->targetBranch,
$this->targetBranch
);
}
private function ensureFeatureBranchInSync(): void
{
$this->ensureBranchInSyncWithUpstream(
$this->localBranch,
$this->remoteBranch
);
}
private function ensureBranchInSyncWithUpstream(
string $localBranch,
string $remoteBranch
): void {
echo sprintf(
'Ensuring that %s is in sync with its upstream...',
$localBranch
) . PHP_EOL;
$localCommitTip = $this->tipCommitOfBranch($localBranch);
$remoteCommitTip = $this->tipCommitOfBranch(sprintf(
'origin/%s',
$remoteBranch
));
if ($localCommitTip != $remoteCommitTip) {
$this->dieWithMessage(sprintf(
'Branch %s was out of date, needs rebasing. Aborting.',
$localBranch
));
}
}
private function tipCommitOfBranch(string $branchName): string
{
return $this->run(
sprintf('git rev-parse %s', $branchName),
self::RUN_TYPE_QUERY
);
}
private function checkoutTargetBranch(): void
{
echo sprintf('Checking out %s...' . PHP_EOL, $this->targetBranch);
$this->run(
sprintf('git checkout %s', $this->targetBranch),
self::RUN_TYPE_COMMAND
);
}
private function mergeLocalBranch(): void
{
echo sprintf(
'Merging %s into %s...' . PHP_EOL,
$this->localBranch,
$this->targetBranch
);
$mergeCommand = sprintf('git merge --ff-only %s', $this->localBranch);
if (!$this->run($mergeCommand, self::RUN_TYPE_COMMAND)) {
// Switch back to the previous branch.
$this->run('git checkout -', self::RUN_TYPE_COMMAND);
$this->dieWithMessage(sprintf(
'Branch %s is not fast-forwardable.',
$this->localBranch
));
}
}
public function pushTargetBranch(): void
{
print(sprintf('Pushing updated %s branch...', $this->targetBranch));
$this->run(
sprintf('git push origin %s', $this->targetBranch),
self::RUN_TYPE_COMMAND
);
}
public function deleteRemoteBranch(): void
{
echo 'Deleting remote branch...' . PHP_EOL;
$this->run(
sprintf('git push origin :%s', $this->remoteBranch),
self::RUN_TYPE_COMMAND
);
}
public function deleteLocalBranch(): void
{
echo 'Deleting local branch...' . PHP_EOL;
$this->run(
sprintf('git branch -d %s', $this->localBranch),
self::RUN_TYPE_COMMAND
);
}
private function getArg(string $shortOpts, array $longOpts = []): ?string
{
if (!$values = getopt($shortOpts, $longOpts)) {
return NULL;
}
return current($values);
}
private function hasArg(string $shortOpts, array $longOpts = []): bool
{
return !empty(getopt($shortOpts, $longOpts));
}
private function isForce(): bool
{
return $this->hasArg('f::', ['force::']);
}
/**
* Run the command.
*
* @return bool|string
* If the type is 'command', the method will return if there were any
* errors when running the command based on its return code.
*
* If the type is 'query', then the output of the command will be returned
* as a string.
*/
private function run(string $command, string $type)
{
switch ($type) {
case self::RUN_TYPE_COMMAND:
// Perform the command, hiding the original output and return
// whether or not there were errors.
@exec("$command", $output, $return);
return $return == 0;
case self::RUN_TYPE_QUERY:
// Perform the command and return the output.
return exec($command, $output);
}
}
private function dieWithMessage(string $message): void
{
echo sprintf("\e[31m%s\e[0m", $message);
exit(1);
}
private function exitWithWarning(string $message): void
{
echo sprintf("\e[33m%s\e[0m", $message);
exit(2);
}
}
(new ClosesPullRequests())->__invoke();

7
bin/bin/git-cm Executable file
View file

@ -0,0 +1,7 @@
#!/usr/bin/env bash
if [[ $# > 0 ]]; then
git commit -m "$@"
else
git commit -v
fi

16
bin/bin/git-continue Executable file
View file

@ -0,0 +1,16 @@
#!/bin/bash
# Continue a rebase or cherry-pick in the event of conflicts.
if [[ -e .git/CHERRY_PICK_HEAD ]] ; then
exec git cherry-pick --continue "$@"
elif [[ -e .git/rebase-apply/applying ]] ; then
exec git rebase --continue "$@"
elif [[ -e .git/rebase-apply ]] ; then
exec git rebase --continue "$@"
elif [[ -e .git/rebase-merge ]] ; then
exec git rebase --continue "$@"
else
echo git-abort: unknown state
exit -1
fi

View file

@ -0,0 +1,15 @@
#!/bin/sh
set -e
if [ "$#" -lt 1 ]; then
echo "Error: Not enough arguments."
exit l
fi
# Create a new branch including any additional arguments.
git checkout -b "$@"
# Push the branch to origin, bypassing any Git hooks.
new_branch_name=$1
git push --no-verify -u origin "${new_branch_name}:opd-${new_branch_name}"

View file

@ -0,0 +1,42 @@
#!/usr/bin/env php
<?php
function extractBranchNamesFromInfo(string $branchInfo): array
{
$branchNames = array_map(function (string $branchInfo): string {
preg_match('/\s*((\w|-|\/)+)\s*/', $branchInfo, $matches);
return $matches[1] ?? '';
}, explode(PHP_EOL, $branchInfo));
return array_filter($branchNames);
}
function filterIgnoredBranches(array $branchNames): array
{
return array_filter($branchNames, function (string $branchName): bool {
return !in_array($branchName, ['develop', 'master', 'staging', 'production']);
});
}
$branchInfo = shell_exec('git branch -vv | grep ": gone]"');
# Return early if there are no branches to delete.
if ($branchInfo === NULL) {
return;
}
$branchNames = extractBranchNamesFromInfo($branchInfo);
$filteredBranchNames = filterIgnoredBranches($branchNames);
$currentBranch = exec('git rev-parse --abbrev-ref HEAD');
foreach ($filteredBranchNames as $branchName) {
if ($branchName == $currentBranch) {
echo "Cannot delete {$branchName} as it is the current branch.";
continue;
}
echo "Deleting {$branchName}...";
exec("git branch -D ${branchName}");
}

View file

@ -0,0 +1,19 @@
#!/usr/bin/env zsh
# Usage: instead of
#
# git rebase -i master
#
# run this:
#
# git master-to-main-wrapper rebase -i %BRANCH%
#
# It will replace the literal string `%BRANCH%` with "main" (preferred) or
# "master" depending on what the current repository uses.
command=$*
branchname=$(main-or-master-branch)
replaced_commands=$(echo $command | sed "s/%BRANCH%/$branchname/g")
# sh_glob ignores special meaning of parentheses so that fancy logs like this
# work: `git master-to-main-wrapper log --format='%w(78)%s%n%+b'`
zsh -c "setopt sh_glob; git ${replaced_commands}"

26
bin/bin/git-opr Executable file
View file

@ -0,0 +1,26 @@
#!/bin/bash
set -e
ensure_is_published() {
[[ ! $is_published ]] && git publish
}
is_published() {
echo $(git upstream)
}
open_or_build_pull_request() {
type gh &>/dev/null
if [ $? -ne 0 ]; then
echo "Error: gh command not found."
exit 1
fi
# Load an existing PR, or create a new one.
gh pr view --web || gh pr create --assignee opdavies --web
}
ensure_is_published
open_or_build_pull_request

15
bin/bin/git-publish Executable file
View file

@ -0,0 +1,15 @@
#!/usr/bin/env php
<?php
/**
* Usage: git publish
*/
$currentBranch = exec('git rev-parse --abbrev-ref HEAD');
if (in_array($currentBranch, ['develop', 'main', 'master', 'staging', 'production'])) {
print "Currently on ${currentBranch}. Aborting.";
exit(1);
}
exec("git push -u origin $currentBranch:opd-{$currentBranch}");

21
bin/bin/git-up Executable file
View file

@ -0,0 +1,21 @@
#!/usr/bin/env bash
# Usage: git up {branch} {remote}
set -e
if [[ $# < 1 ]]; then
echo "You must specify a branch name to update"
exit 1
fi
BRANCH=$1
REMOTE=${2:-origin}
git checkout ${BRANCH} && \
git fetch ${REMOTE} && \
echo && \
git sl ${BRANCH}..${REMOTE}/${BRANCH} && \
echo && \
git pull --quiet && \
git checkout -

28
bin/bin/git.sh Executable file
View file

@ -0,0 +1,28 @@
#!/bin/bash
# The MIT License (MIT)
# Copyright (c) 2013 Alvin Abad
if [ $# -eq 0 ]; then
echo "Git wrapper script that can specify an ssh-key file
Usage:
git.sh -i ssh-key-file git-command
"
exit 1
fi
# remove temporary file on exit
trap 'rm -f /tmp/.git_ssh.$$' 0
if [ "$1" = "-i" ]; then
SSH_KEY=$2; shift; shift
echo "ssh -i $SSH_KEY \$@" > /tmp/.git_ssh.$$
chmod +x /tmp/.git_ssh.$$
export GIT_SSH=/tmp/.git_ssh.$$
fi
# in case the git command is repeated
[ "$1" = "git" ] && shift
# Run the git command
git "$@"

10
bin/bin/main-or-master-branch Executable file
View file

@ -0,0 +1,10 @@
#!/bin/zsh
# Check if we should use the `main` or `master` branch for this repo.
# Prefer `main` to `master`.
if git show-ref --quiet origin/main || git rev-parse main &>/dev/null; then
echo main
else
echo master
fi

8
bin/bin/phpunit-or-pest Executable file
View file

@ -0,0 +1,8 @@
#!/usr/bin/env bash
if [[ -f "vendor/bin/pest" ]]; then
echo "pest"
exit 0
fi
echo "phpunit"

39
bin/bin/tmux-sessioniser Executable file
View file

@ -0,0 +1,39 @@
#!/bin/bash
# Quickly navigate between different directories using fzf and tmux sessions
# (Thanks, ThePrimeagen!).
#
# https://github.com/ThePrimeagen/.dotfiles/blob/master/bin/.local/bin/tmux-sessionizer
# https://frontendmasters.com/workshops/dev-productivity
if [[ $# -eq 1 ]]; then
selected=$1
else
# Get the session name from fuzzy-finding list of directories and generating a
# tmux-safe version.
selected=$(find ~/ ~/Code ~/Code/clients ~/Code/os ~/Code/Personal ~/Documents/Books ~/Documents/Talks/ -mindepth 1 -maxdepth 1 -type d -not -name ".*" | sort | fzf)
fi
if [[ -z $selected ]]; then
exit 0
fi
is_tmux_running=$(pgrep tmux)
selected_name=$(basename "$selected" | tr . -)
if [[ -z $TMUX ]] && [[ -z $is_tmux_running ]]; then
tmux new-session -s $selected_name -c $selected
exit 0
fi
# Create a new session if tmux does not already have a session matching the
# selected session name.
if ! tmux has-session -t $selected_name 2> /dev/null; then
tmux new-session -s $selected_name -c $selected -d
fi
if [[ -z $TMUX ]]; then
tmux attach-session -t $selected_name
else
tmux switch-client -t $selected_name
fi

38
bin/dotfiles Executable file
View file

@ -0,0 +1,38 @@
#!/bin/bash
set -e
CONFIG_DIR="$HOME/.config/dotfiles"
DOTFILES_DIR="${DOTFILES_DIR:-$HOME/.dotfiles}"
PATH="${PATH}:${HOME}/.local/bin"
clone_or_update_dotfiles() {
if ! [[ -d "$DOTFILES_DIR" ]]; then
git clone "https://github.com/opdavies/dotfiles.git" "$DOTFILES_DIR"
else
git -C "$DOTFILES_DIR" pull
fi
}
create_config_dir() {
mkdir -p "${CONFIG_DIR}"
}
install_dependencies() {
ansible-galaxy install -r "${DOTFILES_DIR}/requirements.yml"
}
install_ansible() {
sudo apt-get -yqq update
sudo apt-get -yqq install python3-pip
pip install ansible --user
}
run_playbook() {
ansible-playbook --diff --extra-vars "@${CONFIG_DIR}/values.yaml" --vault-password-file=${CONFIG_DIR}/vault-password.txt "${DOTFILES_DIR}/main.yaml" "${@}"
}
clone_or_update_dotfiles
install_ansible
install_dependencies
run_playbook "${@}"

7
bin/tmuxinator-fzf Executable file
View file

@ -0,0 +1,7 @@
#!/usr/bin/env bash
# Use fzf to select a project to open with tmuxinator.
set -euo pipefail
tmuxinator list -n | tail -n +2 | fzf | xargs tmuxinator start

627
flake.lock generated
View file

@ -1,627 +0,0 @@
{
"nodes": {
"agenix": {
"inputs": {
"darwin": "darwin",
"home-manager": "home-manager",
"nixpkgs": [
"nixpkgs"
],
"systems": "systems"
},
"locked": {
"lastModified": 1754433428,
"narHash": "sha256-NA/FT2hVhKDftbHSwVnoRTFhes62+7dxZbxj5Gxvghs=",
"owner": "ryantm",
"repo": "agenix",
"rev": "9edb1787864c4f59ae5074ad498b6272b3ec308d",
"type": "github"
},
"original": {
"owner": "ryantm",
"repo": "agenix",
"type": "github"
}
},
"bop-scripts": {
"flake": false,
"locked": {
"lastModified": 1756931648,
"narHash": "sha256-bfAmJ1IY0B6eNbJvoWkUMQ7Ya4ShrIoVSdQrnE/cn40=",
"owner": "breadonpenguins",
"repo": "scripts",
"rev": "d04bcbe63176e623e1ce8edc4c3840c506a28d96",
"type": "github"
},
"original": {
"owner": "breadonpenguins",
"repo": "scripts",
"type": "github"
}
},
"conf-vim": {
"flake": false,
"locked": {
"lastModified": 1507549264,
"narHash": "sha256-AjiTJsoim0BAnyfqk1IQzNsa6jhFM2+A66E7q9sJqz0=",
"owner": "tjdevries",
"repo": "conf.vim",
"rev": "a716df0fd5d7ba558c07dac2e07f05d5eba11afb",
"type": "github"
},
"original": {
"owner": "tjdevries",
"repo": "conf.vim",
"type": "github"
}
},
"darwin": {
"inputs": {
"nixpkgs": [
"agenix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1744478979,
"narHash": "sha256-dyN+teG9G82G+m+PX/aSAagkC+vUv0SgUw3XkPhQodQ=",
"owner": "lnl7",
"repo": "nix-darwin",
"rev": "43975d782b418ebf4969e9ccba82466728c2851b",
"type": "github"
},
"original": {
"owner": "lnl7",
"ref": "master",
"repo": "nix-darwin",
"type": "github"
}
},
"devshell": {
"inputs": {
"nixpkgs": [
"git-repo-updater",
"nixpkgs"
]
},
"locked": {
"lastModified": 1741473158,
"narHash": "sha256-kWNaq6wQUbUMlPgw8Y+9/9wP0F8SHkjy24/mN3UAppg=",
"owner": "numtide",
"repo": "devshell",
"rev": "7c9e793ebe66bcba8292989a68c0419b737a22a0",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "devshell",
"type": "github"
}
},
"disko": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1756733629,
"narHash": "sha256-dwWGlDhcO5SMIvMSTB4mjQ5Pvo2vtxvpIknhVnSz2I8=",
"owner": "nix-community",
"repo": "disko",
"rev": "a5c4f2ab72e3d1ab43e3e65aa421c6f2bd2e12a1",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "disko",
"type": "github"
}
},
"edit-alternate-vim": {
"flake": false,
"locked": {
"lastModified": 1635180789,
"narHash": "sha256-mEKnqYAhgrdxPRoKf4S4yYecdFIHGg8bDxpqPuC1+S4=",
"owner": "tjdevries",
"repo": "edit_alternate.vim",
"rev": "ef3019115d9bb7ffd691d2859eda213dd99e0b0a",
"type": "github"
},
"original": {
"owner": "tjdevries",
"repo": "edit_alternate.vim",
"type": "github"
}
},
"flake-parts": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
"lastModified": 1756770412,
"narHash": "sha256-+uWLQZccFHwqpGqr2Yt5VsW/PbeJVTn9Dk6SHWhNRPw=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "4524271976b625a4a605beefd893f270620fd751",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"flake-parts_2": {
"inputs": {
"nixpkgs-lib": [
"nur",
"nixpkgs"
]
},
"locked": {
"lastModified": 1733312601,
"narHash": "sha256-4pDvzqnegAfRkPwO3wmwBhVi/Sye1mzps0zHWYnP88c=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "205b12d8b7cd4802fbcb8e8ef6a0f1408781a4f9",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"flake-utils": {
"inputs": {
"systems": "systems_2"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"git-repo-updater": {
"inputs": {
"devshell": "devshell",
"flake-parts": [
"flake-parts"
],
"import-tree": [
"import-tree"
],
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1757018109,
"narHash": "sha256-KfRzBPOOM5cf8mFVeWjV7TGa3p+ul/flxnUdwGW4Sds=",
"ref": "refs/heads/main",
"rev": "63235768261976efe0d9c825e69c44fff8c80e5d",
"revCount": 1,
"type": "git",
"url": "https://code.oliverdavies.uk/opdavies/git-repo-updater"
},
"original": {
"type": "git",
"url": "https://code.oliverdavies.uk/opdavies/git-repo-updater"
}
},
"home-manager": {
"inputs": {
"nixpkgs": [
"agenix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1745494811,
"narHash": "sha256-YZCh2o9Ua1n9uCvrvi5pRxtuVNml8X2a03qIFfRKpFs=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "abfad3d2958c9e6300a883bd443512c55dfeb1be",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "home-manager",
"type": "github"
}
},
"home-manager_2": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1756991914,
"narHash": "sha256-4ve/3ah5H/SpL2m3qmZ9GU+VinQYp2MN1G7GamimTds=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "b08f8737776f10920c330657bee8b95834b7a70f",
"type": "github"
},
"original": {
"owner": "nix-community",
"ref": "master",
"repo": "home-manager",
"type": "github"
}
},
"import-tree": {
"locked": {
"lastModified": 1752730890,
"narHash": "sha256-GES8fapSLGz36MMPRVNkSUWXUTtqvGQNXHjRmRLfJUY=",
"owner": "vic",
"repo": "import-tree",
"rev": "6ebb8cb87987b20264c09296166543fd3761d274",
"type": "github"
},
"original": {
"owner": "vic",
"repo": "import-tree",
"type": "github"
}
},
"ixx": {
"inputs": {
"flake-utils": [
"nixvim",
"nuschtosSearch",
"flake-utils"
],
"nixpkgs": [
"nixvim",
"nuschtosSearch",
"nixpkgs"
]
},
"locked": {
"lastModified": 1754860581,
"narHash": "sha256-EM0IE63OHxXCOpDHXaTyHIOk2cNvMCGPqLt/IdtVxgk=",
"owner": "NuschtOS",
"repo": "ixx",
"rev": "babfe85a876162c4acc9ab6fb4483df88fa1f281",
"type": "github"
},
"original": {
"owner": "NuschtOS",
"ref": "v0.1.1",
"repo": "ixx",
"type": "github"
}
},
"nix-index-database": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1756612744,
"narHash": "sha256-/glV6VAq8Va3ghIbmhET3S1dzkbZqicsk5h+FtvwiPE=",
"owner": "nix-community",
"repo": "nix-index-database",
"rev": "3fe768e1f058961095b4a0d7a2ba15dc9736bdc6",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nix-index-database",
"type": "github"
}
},
"nixos-hardware": {
"locked": {
"lastModified": 1756925795,
"narHash": "sha256-kUb5hehaikfUvoJDEc7ngiieX88TwWX/bBRX9Ar6Tac=",
"owner": "NixOS",
"repo": "nixos-hardware",
"rev": "ba6fab29768007e9f2657014a6e134637100c57d",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "master",
"repo": "nixos-hardware",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1756787288,
"narHash": "sha256-rw/PHa1cqiePdBxhF66V7R+WAP8WekQ0mCDG4CFqT8Y=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "d0fc30899600b9b3466ddb260fd83deb486c32f1",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-lib": {
"locked": {
"lastModified": 1754788789,
"narHash": "sha256-x2rJ+Ovzq0sCMpgfgGaaqgBSwY+LST+WbZ6TytnT9Rk=",
"owner": "nix-community",
"repo": "nixpkgs.lib",
"rev": "a73b9c743612e4244d865a2fdee11865283c04e6",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nixpkgs.lib",
"type": "github"
}
},
"nixpkgs-stable": {
"locked": {
"lastModified": 1751274312,
"narHash": "sha256-/bVBlRpECLVzjV19t5KMdMFWSwKLtb5RyXdjz3LJT+g=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "50ab793786d9de88ee30ec4e4c24fb4236fc2674",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-24.11",
"repo": "nixpkgs",
"type": "github"
}
},
"nixvim": {
"inputs": {
"flake-parts": [
"flake-parts"
],
"nixpkgs": [
"nixpkgs"
],
"nuschtosSearch": "nuschtosSearch",
"systems": "systems_3"
},
"locked": {
"lastModified": 1756946299,
"narHash": "sha256-N4PjGA0rittpNZGscKPel+mr/dMcKF73j0yr4rbG3T0=",
"owner": "nix-community",
"repo": "nixvim",
"rev": "63496f00c681b3e200bd17878a43ec68b7139a66",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nixvim",
"type": "github"
}
},
"nur": {
"inputs": {
"flake-parts": "flake-parts_2",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1757050467,
"narHash": "sha256-Rps0Ga0g/TdY49rR2ZRBsdBYybSzPccEsaI9IvwuE98=",
"owner": "nix-community",
"repo": "NUR",
"rev": "985abf0197c75dd64c24691a7e5e0acf308d7f20",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "NUR",
"type": "github"
}
},
"nuschtosSearch": {
"inputs": {
"flake-utils": "flake-utils",
"ixx": "ixx",
"nixpkgs": [
"nixvim",
"nixpkgs"
]
},
"locked": {
"lastModified": 1755555503,
"narHash": "sha256-WiOO7GUOsJ4/DoMy2IC5InnqRDSo2U11la48vCCIjjY=",
"owner": "NuschtOS",
"repo": "search",
"rev": "6f3efef888b92e6520f10eae15b86ff537e1d2ea",
"type": "github"
},
"original": {
"owner": "NuschtOS",
"repo": "search",
"type": "github"
}
},
"root": {
"inputs": {
"agenix": "agenix",
"bop-scripts": "bop-scripts",
"conf-vim": "conf-vim",
"disko": "disko",
"edit-alternate-vim": "edit-alternate-vim",
"flake-parts": "flake-parts",
"git-repo-updater": "git-repo-updater",
"home-manager": "home-manager_2",
"import-tree": "import-tree",
"nix-index-database": "nix-index-database",
"nixos-hardware": "nixos-hardware",
"nixpkgs": "nixpkgs",
"nixpkgs-stable": "nixpkgs-stable",
"nixvim": "nixvim",
"nur": "nur",
"rwxrob-dot": "rwxrob-dot",
"standard-vim": "standard-vim",
"vim-heritage": "vim-heritage",
"vim-textobj-xmlattr": "vim-textobj-xmlattr",
"voidrice": "voidrice",
"zet": "zet"
}
},
"rwxrob-dot": {
"flake": false,
"locked": {
"lastModified": 1751898094,
"narHash": "sha256-kGpHL2l9p/yOtmG+AZvOb0Y5mH1d+Zoh2dd5N3Xjizc=",
"owner": "rwxrob",
"repo": "dot",
"rev": "90794c77061f270078e847af45c376610768c6e2",
"type": "github"
},
"original": {
"owner": "rwxrob",
"repo": "dot",
"type": "github"
}
},
"standard-vim": {
"flake": false,
"locked": {
"lastModified": 1539613748,
"narHash": "sha256-9VwkvV1Dv6cE4uDkPp36DozjWJOclDR883yDMYw000E=",
"owner": "tjdevries",
"repo": "standard.vim",
"rev": "b333ef9a9cf6cf66536deda017a542843613fa75",
"type": "github"
},
"original": {
"owner": "tjdevries",
"repo": "standard.vim",
"type": "github"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_2": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_3": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"vim-heritage": {
"flake": false,
"locked": {
"lastModified": 1716350150,
"narHash": "sha256-YzqP2+Go8bW3heFyzzcS/91LrMkwjpZ89+ptrjjBKrM=",
"owner": "jessarcher",
"repo": "vim-heritage",
"rev": "574baeb0679681a710adce5110a0d8b2ae1c2637",
"type": "github"
},
"original": {
"owner": "jessarcher",
"repo": "vim-heritage",
"type": "github"
}
},
"vim-textobj-xmlattr": {
"flake": false,
"locked": {
"lastModified": 1464940962,
"narHash": "sha256-+91FVP95oh00flINdltqx6qJuijYo56tHIh3J098G2Q=",
"owner": "whatyouhide",
"repo": "vim-textobj-xmlattr",
"rev": "694a297f1d75fd527e87da9769f3c6519a87ebb1",
"type": "github"
},
"original": {
"owner": "whatyouhide",
"repo": "vim-textobj-xmlattr",
"type": "github"
}
},
"voidrice": {
"flake": false,
"locked": {
"lastModified": 1744355318,
"narHash": "sha256-9U1Do0w2oT5E6uZxSKoHAzbGbSLQRQlT65KcPGzwhW8=",
"owner": "lukesmithxyz",
"repo": "voidrice",
"rev": "f853f1884a8f0c244765192dc6f5a910a7e2b8e5",
"type": "github"
},
"original": {
"owner": "lukesmithxyz",
"repo": "voidrice",
"type": "github"
}
},
"zet": {
"flake": false,
"locked": {
"lastModified": 1758576585,
"narHash": "sha256-hWQE45nFaSN8agYMP8xt5kaUMfBXVj5k9zInZNs/xAI=",
"ref": "refs/heads/main",
"rev": "23505f6c31c7cc903e63621b52b5f92eea1facc5",
"revCount": 35,
"type": "git",
"url": "https://code.oliverdavies.uk/opdavies/zet"
},
"original": {
"type": "git",
"url": "https://code.oliverdavies.uk/opdavies/zet"
}
}
},
"root": "root",
"version": 7
}

106
flake.nix
View file

@ -1,106 +0,0 @@
{
inputs = {
agenix = {
inputs.nixpkgs.follows = "nixpkgs";
url = "github:ryantm/agenix";
};
bop-scripts = {
flake = false;
url = "github:breadonpenguins/scripts";
};
conf-vim = {
flake = false;
url = "github:tjdevries/conf.vim";
};
disko = {
inputs.nixpkgs.follows = "nixpkgs";
url = "github:nix-community/disko";
};
edit-alternate-vim = {
flake = false;
url = "github:tjdevries/edit_alternate.vim";
};
flake-parts.url = "github:hercules-ci/flake-parts";
git-repo-updater = {
inputs.flake-parts.follows = "flake-parts";
inputs.import-tree.follows = "import-tree";
inputs.nixpkgs.follows = "nixpkgs";
url = "git+https://code.oliverdavies.uk/opdavies/git-repo-updater";
};
home-manager = {
inputs.nixpkgs.follows = "nixpkgs";
url = "github:nix-community/home-manager/master";
};
import-tree.url = "github:vic/import-tree";
nix-index-database = {
inputs.nixpkgs.follows = "nixpkgs";
url = "github:nix-community/nix-index-database";
};
nixos-hardware.url = "github:NixOS/nixos-hardware/master";
nixvim = {
inputs.flake-parts.follows = "flake-parts";
inputs.nixpkgs.follows = "nixpkgs";
url = "github:nix-community/nixvim";
};
nixpkgs-stable.url = "github:nixos/nixpkgs/nixos-24.11";
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
nur = {
inputs.nixpkgs.follows = "nixpkgs";
url = "github:nix-community/NUR";
};
rwxrob-dot = {
flake = false;
url = "github:rwxrob/dot";
};
standard-vim = {
flake = false;
url = "github:tjdevries/standard.vim";
};
vim-heritage = {
flake = false;
url = "github:jessarcher/vim-heritage";
};
vim-textobj-xmlattr = {
flake = false;
url = "github:whatyouhide/vim-textobj-xmlattr";
};
voidrice = {
flake = false;
url = "github:lukesmithxyz/voidrice";
};
zet = {
flake = false;
url = "git+https://code.oliverdavies.uk/opdavies/zet";
};
};
outputs =
inputs@{ flake-parts, ... }:
flake-parts.lib.mkFlake { inherit inputs; } {
flake = {
overlays = import ./overlays { inherit inputs; };
};
imports = [ (inputs.import-tree ./modules) ];
};
}

52
group_vars/all Normal file
View file

@ -0,0 +1,52 @@
default_roles:
- alacritty
- awesome-wm
- cargo
- copyq
- ctop
- dconf
- debugger
- delta
- discord
- docker
- filezilla
- flameshot
- fonts
- fzf
- git
- github-cli
- github-desktop
- gnome-tweak-tools
- google-chrome
- htop
- jq
- kdenlive
- mysql-client
- neovim
- neovim-lsp
- neovim-packer
- notion-app
- npm
- obs-studio
- pdf-arranger
- platformsh-cli
- pocketcasts
- postman
- projects
- pulumi
- pv
- ripgrep
- skype
- slack
- ssh
- stylua
- teams
- tldr
- tmux
- tmuxinator
- todoist
- tree
- vlc
- zoom
- zsh
- zsh-antigen

View file

@ -1,13 +0,0 @@
{ pkgs, ... }:
{
imports = [
./nixedo/email-filters.nix
];
home.packages = with pkgs; [
import-to-jellyfin
vic
yt-dlp
];
}

View file

@ -1,45 +0,0 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.nixedo.${name};
name = "email-filters";
in
{
options.nixedo.${name} = {
configFile = lib.mkOption {
default = "${config.xdg.userDirs.extraConfig.XDG_REPOS_DIR}/${name}/config.lua";
internal = true;
};
};
config = {
systemd.user = {
services.${name} = {
Install.WantedBy = [ "default.target" ];
Service = {
ExecStart = "${lib.getExe pkgs.imapfilter} -c ${cfg.configFile}";
Type = "oneshot";
};
Unit.Description = name;
};
timers.${name} = {
Install.WantedBy = [ "timers.target" ];
Timer = {
OnCalendar = "*-*-* 06..23:00/5";
Unit = "${name}.service";
};
Unit.Description = "Automatically runs email filters with imapfilter.";
};
};
};
}

View file

@ -1,37 +0,0 @@
{ config, pkgs, ... }:
{
programs = {
zsh.shellAliases =
let
inherit (config.xdg.userDirs) documents;
in
{
"wiki-push" =
"rsync -avzP ${documents}/wiki nixedo.oliverdavies.uk:${documents} --delete --delete-after";
};
};
home.packages = with pkgs; [
backup-websites
build-glove80
count-tags
create-script
get-tags
qrencode
mounter
move-firefox-screenshots
set-background
tag-release
time-until
timer
unmounter
update-all-git-repos
vic
];
xdg.configFile."pam-gnupg".text = ''
098EE055DAD2B9CB68154C6759DD38292D2273B6
1E21B58D69FFEFAD077F152A50FEA938A3413F50
'';
}

2
hosts.ini Normal file
View file

@ -0,0 +1,2 @@
[localhost]
127.0.0.1 ansible_connection=local

View file

@ -1,102 +0,0 @@
{
hostname,
inputs,
outputs,
pkgs,
self,
stateVersion,
system,
username,
...
}:
{
imports = [
./users
inputs.home-manager.nixosModules.home-manager
];
nix = {
settings = {
auto-optimise-store = true;
download-buffer-size = "104857600";
experimental-features = [
"nix-command"
"flakes"
];
warn-dirty = false;
};
};
programs.zsh.enable = true;
users.defaultUserShell = pkgs.zsh;
environment.systemPackages = with pkgs; [
cryptsetup
fastfetch
mermaid-cli
mkcert
];
home-manager = {
backupFileExtension = "backup";
extraSpecialArgs = {
inherit
hostname
inputs
outputs
self
system
username
;
};
useGlobalPkgs = true;
useUserPackages = true;
users."${username}" = import ./home.nix;
};
nixpkgs.overlays = [
inputs.nur.overlays.default
outputs.overlays.additions
outputs.overlays.modifications
outputs.overlays.stable-packages
];
nix.extraOptions = ''
trusted-users = root ${username}
'';
networking.hostName = hostname;
time.timeZone = "Europe/London";
i18n = {
defaultLocale = "en_GB.UTF-8";
extraLocaleSettings = {
LC_ADDRESS = "en_GB.UTF-8";
LC_IDENTIFICATION = "en_GB.UTF-8";
LC_MEASUREMENT = "en_GB.UTF-8";
LC_MONETARY = "en_GB.UTF-8";
LC_NAME = "en_GB.UTF-8";
LC_NUMERIC = "en_GB.UTF-8";
LC_PAPER = "en_GB.UTF-8";
LC_TELEPHONE = "en_GB.UTF-8";
LC_TIME = "en_GB.UTF-8";
};
};
console.keyMap = "uk";
security.sudo.wheelNeedsPassword = false;
system.stateVersion = stateVersion;
}

View file

@ -1,102 +0,0 @@
{
config,
inputs,
outputs,
system,
...
}:
let
pkgs = import inputs.nixpkgs {
inherit system;
overlays = [
outputs.overlays.additions
outputs.overlays.stable-packages
];
};
inherit (pkgs) lib;
inherit (config.xdg)
cacheHome
configHome
dataHome
stateHome
;
in
{
home.username = "opdavies";
home.homeDirectory = "/home/${config.home.username}";
home.packages = with pkgs; [
cachix
delta
entr
gcc
git
git-crypt
gnupg
inotify-tools
jq
killall
lua
mob
pv
simple-http-server
sshs
tldr
tree
tree-sitter
unzip
w3m
watchexec
wget
xclip
xdg-utils
zbar
];
programs.home-manager.enable = true;
home.sessionVariables = {
EDITOR = "nvim";
IMAPFILTER_HOME = "${configHome}/imapfilter";
LANG = "en_GB.UTF-8";
LC_ALL = "en_GB.UTF-8";
LC_CTYPE = "en_GB.UTF-8";
PASSWORD_STORE_DIR = "${dataHome}/pass";
PATH = lib.concatStringsSep ":" [
"$PATH"
"$HOME/go/bin"
"./vendor/bin"
"./node_modules/.bin"
];
PULUMI_SKIP_UPDATE_CHECK = "true";
W3M_DIR = "${stateHome}/w3m";
WGETRC = "${configHome}/wgetrc";
XDG_CONFIG_HOME = config.xdg.configHome;
XDG_DATA_HOME = dataHome;
XDG_STATE_HOME = stateHome;
};
xdg = {
configFile = {
"${config.home.sessionVariables.WGETRC}".text = ''
hsts-file = "${cacheHome}/wget-hsts"
'';
};
userDirs = {
enable = true;
extraConfig = {
XDG_REPOS_DIR = "${config.home.homeDirectory}/Code";
};
};
};
# Nicely reload system units when changing configs.
systemd.user.startServices = "sd-switch";
home.stateVersion = "22.05"; # Please read the comment before changing.
}

View file

@ -1,5 +0,0 @@
{
imports = [
./opdavies.nix
];
}

View file

@ -1,7 +0,0 @@
{ config, self, ... }:
{
users.users.opdavies = { };
home-manager.users.opdavies = import "${self}/home-manager/opdavies/${config.networking.hostName}.nix";
}

View file

@ -1,51 +0,0 @@
# 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, pkgs, ... }:
{
imports = [
inputs.agenix.nixosModules.default
../common
./hardware-configuration.nix
./homelab.nix
./modules
./ports.nix
./secrets.nix
./services
../../users/opdavies.nix
];
# TODO: why didn't it work when adding this to jitsi.nix?
nixpkgs.config.permittedInsecurePackages = [
"jitsi-meet-1.0.8043"
];
services.logind.lidSwitchExternalPower = "ignore";
boot.loader = {
efi.canTouchEfiVariables = true;
systemd-boot.enable = true;
};
networking.networkmanager.enable = true;
users.users.opdavies.extraGroups = [ "media" ];
powerManagement.powertop.enable = true;
users.groups.media = { };
networking.firewall.allowedTCPPorts = [
80
443
];
environment.systemPackages = with pkgs; [
tree
vim
];
}

View file

@ -1,54 +0,0 @@
# 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"
"thunderbolt"
"nvme"
"usb_storage"
"sd_mod"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
fileSystems."/" = {
device = "/dev/disk/by-uuid/40649879-4ee6-4668-8257-fe81a7773024";
fsType = "ext4";
};
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/24B1-88CB";
fsType = "vfat";
options = [
"fmask=0077"
"dmask=0077"
];
};
swapDevices = [ ];
# 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
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
networking.useDHCP = lib.mkDefault true;
# networking.interfaces.enp0s20f0u1.useDHCP = lib.mkDefault true;
# networking.interfaces.wlo1.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

View file

@ -1,21 +0,0 @@
{
homelab = {
enable = true;
cloudflared.tunnelId = "e1514105-327f-4984-974e-e2fbaca76466";
domain = "oliverdavies.uk";
services = {
audiobookshelf.enable = true;
home-assistant.enable = true;
homepage-dashboard.enable = true;
jitsi.enable = true;
paperless.enable = true;
peertube.enable = true;
tubearchivist.enable = true;
uptime-kuma.enable = true;
vaultwarden.enable = false;
};
};
}

View file

@ -1,57 +0,0 @@
{ config, ... }:
{
security.acme = {
acceptTerms = true;
certs =
let
domain = "oliverdavies.uk";
in
{
${domain} = {
inherit domain;
dnsProvider = "cloudflare";
email = "oliver@oliverdavies.uk";
environmentFile = config.age.secrets.cloudflare.path;
webroot = null;
extraDomainNames =
let
subdomains = [
"2020"
"audiobookshelf"
"bootstrap-with-tailwind"
"code"
"eric"
"florida-drupalcamp-tailwind-css"
"home"
"jellyfin"
"luke"
"mealie"
"nixedo"
"paperless"
"photos"
"phpsw-sculpin-demo"
"rebuilding-acquia"
"rebuilding-bartik"
"rebuilding-bristol-js"
"rebuilding-symfony"
"tailwindcss-demo"
"talking-drupal-tailwindcss"
"tubearchivist"
"uptime"
"vaultwarden"
"wp-tailwind"
"www"
"zet"
];
domains = map (subdomain: "${subdomain}.${domain}") subdomains;
in
domains;
};
};
};
}

View file

@ -1,55 +0,0 @@
{ config, lib, ... }:
with lib;
let
cfg = homelab.services.${service};
homelab = config.homelab;
service = "audiobookshelf";
in
{
options.homelab.services.${service} = {
enable = mkEnableOption "Enable ${service}";
url = mkOption {
default = "audiobookshelf.${homelab.domain}";
type = types.str;
};
homepage.name = mkOption {
default = "Audiobookshelf";
type = types.str;
};
homepage.description = mkOption {
default = "Self-hosted audiobook and podcast server";
type = types.str;
};
homepage.icon = mkOption {
default = "audiobookshelf";
type = types.str;
};
homepage.category = mkOption {
default = "Media";
type = types.str;
};
};
config = mkIf cfg.enable {
services = {
${service}.enable = true;
nginx.virtualHosts.${cfg.url} = {
forceSSL = true;
useACMEHost = homelab.domain;
locations."/" = {
proxyPass = "http://localhost:${toString config.services.${service}.port}";
recommendedProxySettings = true;
};
};
};
};
}

View file

@ -1,12 +0,0 @@
{ config, ... }:
{
services.cloudflared = {
enable = true;
tunnels."e1514105-327f-4984-974e-e2fbaca76466" = {
credentialsFile = config.age.secrets.cloudflared.path;
default = "http_status:404";
};
};
}

View file

@ -1,6 +0,0 @@
{
imports = [
# ./pi-hole.nix
./tubearchivist.nix
];
}

View file

@ -1,40 +0,0 @@
{ config, lib, ... }:
let
service = "pihole";
port = config.homelab.ports.${service};
in
{
virtualisation.oci-containers.containers.${service} = {
image = "pihole/pihole:latest";
environment = {
PIHOLE_DNS_1 = "8.8.8.8";
PIHOLE_DNS_2 = "8.8.4.4";
TZ = "Europe/London";
};
volumes = [
"/home/opdavies/pihole/etc-dnsmasq.d:/etc/dnsmasq.d:rw"
"/home/opdavies/pihole/etc-pihole:/etc/pihole:rw"
];
ports = [
"53:53/tcp"
"53:53/udp"
"67:67/udp"
"${port}:80/tcp"
];
log-driver = "journald";
extraOptions = [
"--cap-add=NET_ADMIN"
];
};
systemd.services."podman-pihole".serviceConfig = {
Restart = lib.mkOverride 90 "always";
RestartSec = lib.mkOverride 90 "1s";
};
}

View file

@ -1,334 +0,0 @@
{
config,
inputs,
lib,
pkgs,
...
}:
with lib;
let
cfg = homelab.services.${service};
service = "tubearchivist";
homelab = config.homelab;
port = homelab.ports.${service};
in
{
options.homelab.services.${service} = {
enable = mkEnableOption "Enable ${service}";
url = mkOption {
default = "${service}.${homelab.domain}";
type = types.str;
};
homepage.name = mkOption {
default = "Tube Archivist";
type = types.str;
};
homepage.description = mkOption {
default = "Your self hosted YouTube media server";
type = types.str;
};
homepage.icon = mkOption {
default = "tube-archivist";
type = types.str;
};
homepage.category = mkOption {
default = "Media";
type = types.str;
};
};
config = mkIf cfg.enable {
virtualisation = {
oci-containers.backend = "podman";
podman.enable = true;
};
virtualisation.oci-containers.containers."archivist-es" = {
image = "bbilly1/tubearchivist-es";
environment = {
"ES_JAVA_OPTS" = "-Xms1g -Xmx1g";
"discovery.type" = "single-node";
"path.repo" = "/usr/share/elasticsearch/data/snapshot";
"xpack.security.enabled" = "true";
"cluster.routing.allocation.disk.watermark.flood_stage" = "98%";
"cluster.routing.allocation.disk.watermark.high" = "97%";
"cluster.routing.allocation.disk.watermark.low" = "95%";
};
environmentFiles = [
config.age.secrets.tubearchivist-env.path
];
volumes = [
"tubearchivist_es:/usr/share/elasticsearch/data:rw"
];
log-driver = "journald";
extraOptions = [
"--network-alias=archivist-es"
"--network=tubearchivist_default"
];
};
systemd.services."podman-archivist-es" = {
serviceConfig = {
Restart = mkOverride 90 "always";
RestartMaxDelaySec = mkOverride 90 "1m";
RestartSec = mkOverride 90 "100ms";
RestartSteps = mkOverride 90 9;
};
after = [
"podman-network-tubearchivist_default.service"
"podman-volume-tubearchivist_es.service"
];
requires = [
"podman-network-tubearchivist_default.service"
"podman-volume-tubearchivist_es.service"
];
partOf = [
"podman-compose-tubearchivist-root.target"
];
wantedBy = [
"podman-compose-tubearchivist-root.target"
];
};
virtualisation.oci-containers.containers."archivist-redis" = {
image = "redis";
volumes = [
"tubearchivist_redis:/data:rw"
];
dependsOn = [
"archivist-es"
];
log-driver = "journald";
extraOptions = [
"--network-alias=archivist-redis"
"--network=tubearchivist_default"
];
};
systemd.services."podman-archivist-redis" = {
serviceConfig = {
Restart = mkOverride 90 "always";
RestartMaxDelaySec = mkOverride 90 "1m";
RestartSec = mkOverride 90 "100ms";
RestartSteps = mkOverride 90 9;
};
after = [
"podman-network-tubearchivist_default.service"
"podman-volume-tubearchivist_redis.service"
];
requires = [
"podman-network-tubearchivist_default.service"
"podman-volume-tubearchivist_redis.service"
];
partOf = [
"podman-compose-tubearchivist-root.target"
];
wantedBy = [
"podman-compose-tubearchivist-root.target"
];
};
virtualisation.oci-containers.containers."tubearchivist" = {
image = "bbilly1/tubearchivist";
environment = {
"ES_URL" = "http://archivist-es:9200";
"HOST_GID" = "1000";
"HOST_UID" = "1000";
"REDIS_CON" = "redis://archivist-redis:6379";
"TA_HOST" = "https://${cfg.url}";
"TZ" = "Europe/London";
};
environmentFiles = [
config.age.secrets.tubearchivist-env.path
];
volumes = [
"/mnt/media/${service}/cache:/cache:rw"
"/mnt/media/${service}/media:/youtube:rw"
];
ports = [
"${toString port}:8000/tcp"
];
dependsOn = [
"archivist-es"
"archivist-redis"
];
log-driver = "journald";
extraOptions = [
"--health-cmd=[\"curl\", \"-f\", \"http://localhost:8000/health\"]"
"--health-interval=2m0s"
"--health-retries=3"
"--health-start-period=30s"
"--health-timeout=10s"
"--network-alias=tubearchivist"
"--network=tubearchivist_default"
];
};
systemd.services."podman-tubearchivist" = {
serviceConfig = {
Restart = mkOverride 90 "always";
RestartMaxDelaySec = mkOverride 90 "1m";
RestartSec = mkOverride 90 "100ms";
RestartSteps = mkOverride 90 9;
};
after = [
"podman-network-tubearchivist_default.service"
"podman-volume-tubearchivist_cache.service"
"podman-volume-tubearchivist_media.service"
];
requires = [
"podman-network-tubearchivist_default.service"
"podman-volume-tubearchivist_cache.service"
"podman-volume-tubearchivist_media.service"
];
partOf = [
"podman-compose-tubearchivist-root.target"
];
wantedBy = [
"podman-compose-tubearchivist-root.target"
];
};
systemd.services."podman-network-tubearchivist_default" = {
path = [ pkgs.podman ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
ExecStop = "podman network rm -f tubearchivist_default";
};
script = ''
podman network inspect tubearchivist_default || podman network create tubearchivist_default
'';
partOf = [ "podman-compose-tubearchivist-root.target" ];
wantedBy = [ "podman-compose-tubearchivist-root.target" ];
};
systemd.services."podman-volume-tubearchivist_cache" = {
path = [ pkgs.podman ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
};
script = ''
podman volume inspect tubearchivist_cache || podman volume create tubearchivist_cache
'';
partOf = [ "podman-compose-tubearchivist-root.target" ];
wantedBy = [ "podman-compose-tubearchivist-root.target" ];
};
systemd.services."podman-volume-tubearchivist_es" = {
path = [ pkgs.podman ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
};
script = ''
podman volume inspect tubearchivist_es || podman volume create tubearchivist_es
'';
partOf = [ "podman-compose-tubearchivist-root.target" ];
wantedBy = [ "podman-compose-tubearchivist-root.target" ];
};
systemd.services."podman-volume-tubearchivist_media" = {
path = [ pkgs.podman ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
};
script = ''
podman volume inspect tubearchivist_media || podman volume create tubearchivist_media
'';
partOf = [ "podman-compose-tubearchivist-root.target" ];
wantedBy = [ "podman-compose-tubearchivist-root.target" ];
};
systemd.services."podman-volume-tubearchivist_redis" = {
path = [ pkgs.podman ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
};
script = ''
podman volume inspect tubearchivist_redis || podman volume create tubearchivist_redis
'';
partOf = [ "podman-compose-tubearchivist-root.target" ];
wantedBy = [ "podman-compose-tubearchivist-root.target" ];
};
systemd.targets."podman-compose-tubearchivist-root" = {
unitConfig = {
Description = "Root target generated by compose2nix.";
};
wantedBy = [ "multi-user.target" ];
};
services.nginx.virtualHosts."${cfg.url}" = {
forceSSL = true;
useACMEHost = homelab.domain;
locations."/" = {
proxyPass = "http://localhost:${toString port}";
recommendedProxySettings = true;
proxyWebsockets = true;
extraConfig = ''
proxy_buffering off;
'';
};
};
age.secrets.tubearchivist-env.file = "${inputs.self}/secrets/tubearchivist-env.age";
};
}

View file

@ -1,34 +0,0 @@
{ lib, ... }:
with lib;
{
options.homelab = {
enable = mkEnableOption "Enable homelab services and configuration";
cloudflared.tunnelId = mkOption {
example = "00000000-0000-0000-0000-000000000000";
type = types.str;
};
domain = mkOption {
description = "The base domain to use for this homelab.";
type = types.str;
};
};
imports = [
./acme.nix
./audiobookshelf.nix
./cloudflared.nix
./containers
./forgejo.nix
./home-assistant.nix
./immich.nix
./jellyfin.nix
./jitsi.nix
./nginx
./paperless.nix
./peertube.nix
];
}

View file

@ -1,26 +0,0 @@
{ config, ... }:
{
services.forgejo = {
enable = true;
stateDir = "/var/www/forgejo";
settings = {
server = {
DOMAIN = "code.oliverdavies.uk";
LANDING_PAGE = "explore";
ROOT_URL = "https://${config.services.forgejo.settings.server.DOMAIN}";
SSH_DOMAIN = "ssh.oliverdavies.uk";
};
service.DISABLE_REGISTRATION = true;
ui.DEFAULT_THEME = "forgejo-auto";
};
};
services.cloudflared.tunnels.${config.homelab.cloudflared.tunnelId}.ingress = {
"${config.services.forgejo.settings.server.DOMAIN}" =
"http://localhost:${toString config.services.forgejo.settings.server.HTTP_PORT}";
};
}

View file

@ -1,97 +0,0 @@
{ config, lib, ... }:
with lib;
let
cfg = homelab.services.${service};
homelab = config.homelab;
service = "home-assistant";
in
{
options.homelab.services.${service} = {
enable = mkEnableOption "Enable ${service}";
url = mkOption {
default = "home.${homelab.domain}";
type = types.str;
};
homepage.name = mkOption {
default = "Home Assisant";
type = types.str;
};
homepage.description = mkOption {
default = "Open source home automation that puts local control and privacy first.";
type = types.str;
};
homepage.icon = mkOption {
default = "home-assistant";
type = types.str;
};
homepage.category = mkOption {
default = "Services";
type = types.str;
};
};
config = mkIf cfg.enable {
services = {
home-assistant = {
enable = true;
config = {
external_url = "https://home.${homelab.domain}";
name = "Home";
time_zone = "Europe/London";
unit_system = "metric";
http = {
trusted_proxies = [
"127.0.0.1"
"::1"
];
use_x_forwarded_for = true;
};
mobile_app = { };
# sia = { };
};
extraComponents = [
"default_config"
"elgato"
"hive"
"met"
"mobile_app"
# "sia"
"tplink"
"tplink_tapo"
"weather"
"webostv"
"wiz"
];
extraPackages =
python3Packages: with python3Packages; [
setuptools
];
openFirewall = true;
};
nginx.virtualHosts."${cfg.url}" = {
forceSSL = true;
useACMEHost = homelab.domain;
locations."/" = {
proxyPass = "http://localhost:${toString config.services.${service}.config.http.server_port}";
proxyWebsockets = true;
recommendedProxySettings = true;
};
};
};
};
}

View file

@ -1,25 +0,0 @@
{ config, pkgs, ... }:
{
services.immich = {
enable = true;
group = "media";
mediaLocation = "/mnt/media/immich";
};
services.nginx.virtualHosts."photos.oliverdavies.uk" = {
forceSSL = true;
useACMEHost = "oliverdavies.uk";
locations."/" = {
proxyPass = "http://localhost:${toString config.services.immich.port}";
proxyWebsockets = true;
recommendedProxySettings = true;
};
};
environment.systemPackages = with pkgs; [
immich-cli
immich-go
];
}

View file

@ -1,23 +0,0 @@
{
services.jellyfin = {
enable = true;
configDir = "/mnt/media/jellyfin";
group = "media";
openFirewall = true;
};
services.nginx.virtualHosts."jellyfin.oliverdavies.uk" = {
forceSSL = true;
useACMEHost = "oliverdavies.uk";
locations."/" = {
proxyPass = "http://localhost:8096";
recommendedProxySettings = true;
extraConfig = ''
proxy_buffering off;
'';
};
};
}

View file

@ -1,41 +0,0 @@
{ config, lib, ... }:
let
cfg = config.homelab.services.${service};
homelab = config.homelab;
service = "jitsi";
inherit (lib) mkEnableOption mkOption types;
in
{
options.homelab.services.${service} = {
enable = mkEnableOption "Enable ${service}";
url = mkOption {
default = "meet.${homelab.domain}";
type = types.str;
};
};
config = lib.mkIf cfg.enable {
services = {
jitsi-meet = {
enable = false;
hostName = cfg.url;
secureDomain.enable = true;
};
nginx.virtualHosts.${cfg.url} = {
enableACME = false;
forceSSL = false;
};
cloudflared.tunnels.${homelab.cloudflared.tunnelId}.ingress = {
# TODO: is this the correct port?
${cfg.url} = "http://localhost:5280";
};
};
};
}

View file

@ -1,55 +0,0 @@
{ config, ... }:
let
sites = import ./sites.nix { ports = config.homelab.ports; };
in
{
services = {
nginx = {
enable = true;
virtualHosts = builtins.listToAttrs (
map (site: {
name = site.url;
value = {
root = site.root;
listen = [
{
addr = "localhost";
port = site.port;
}
];
locations."/".tryFiles = "$uri $uri/index.html =404";
extraConfig = builtins.concatStringsSep "\n\n" [
site.extraConfig or ""
''
port_in_redirect off;
# Remove trailing slashes.
rewrite ^/(.*)/$ /$1 permanent;
''
];
};
}) sites
);
};
cloudflared.tunnels."e1514105-327f-4984-974e-e2fbaca76466" = {
ingress = builtins.listToAttrs (
map (site: {
name = site.url;
value = "http://localhost:${toString site.port}";
}) sites
);
};
};
users.users.${config.services.nginx.user}.extraGroups = [ "acme" ];
imports = [ ./www.oliverdavies.uk ];
}

View file

@ -1,51 +0,0 @@
{ ports }:
let
mkSite =
name: overrides:
let
root = "/var/www/vhosts/${name}" + (overrides.rootSuffix or "");
port = ports."nginx-${name}";
url = "${name}.oliverdavies.uk";
in
{ inherit port root url; } // overrides;
sites = [
(mkSite "books" {})
(mkSite "eric" {
rootSuffix = "/public";
extraConfig = ''
add_header X-Robots-Tag "noindex, nofollow";
'';
})
(mkSite "examples" {})
]
++
map
(
domain:
mkSite domain {
extraConfig = ''
add_header X-Robots-Tag "noindex, nofollow";
'';
}
)
[
"bootstrap-with-tailwind"
"florida-drupalcamp-tailwind-css"
"luke"
"phpsw-sculpin-demo"
"rebuilding-acquia"
"rebuilding-bartik"
"rebuilding-bristol-js"
"rebuilding-symfony"
"tailwindcss-demo"
"talking-drupal-tailwindcss"
"wp-tailwind"
"zet"
];
in
sites

View file

@ -1,89 +0,0 @@
{ config, ... }:
let
ports = config.homelab.ports;
port = ports.nginx-website-sculpin;
redirects = builtins.concatStringsSep "\n" (
map (r: "rewrite ^${r.from}/?$ ${r.to} redirect;") (import ./redirects.nix)
);
tome = {
root = "/var/www/vhosts/website-tome";
paths = [
"archive"
"automated-testing"
"core"
"daily/.+"
"examples"
"homelab"
"podcast"
"rss/bb.xml"
"rss/daily.xml"
"sites/default/files"
"testing"
"themes/custom/opdavies"
];
port = ports.nginx-website-tome;
};
tomeLocations = builtins.listToAttrs (
map (path: {
name = "~ ^/${path}";
value = {
root = tome.root;
tryFiles = "$uri $uri.html $uri/index.html =404";
};
}) tome.paths
);
in
{
services = {
nginx.virtualHosts = {
"www.oliverdavies.uk" = {
root = "/var/www/vhosts/website-sculpin";
listen = [
{
inherit port;
addr = "localhost";
}
];
locations = tomeLocations // {
"/".tryFiles = "$uri $uri.html $uri/index.html =404";
};
extraConfig = ''
port_in_redirect off;
# Remove trailing slashes.
rewrite ^/(.*)/$ /$1 permanent;
error_page 404 /404;
rewrite ^/talks/archive/?$ /talks permanent;
rewrite ^/talks/(.*)$ /presentations/$1 permanent;
rewrite ^/talks/?$ /presentations permanent;
${redirects}
'';
};
"oliverdavies.uk" = {
forceSSL = true;
globalRedirect = "www.oliverdavies.uk";
useACMEHost = "oliverdavies.uk";
};
};
cloudflared.tunnels."e1514105-327f-4984-974e-e2fbaca76466".ingress = {
"oliverdavies.uk" = "http://localhost:${toString port}";
"www.oliverdavies.uk" = "http://localhost:${toString port}";
};
};
}

File diff suppressed because it is too large Load diff

View file

@ -1,60 +0,0 @@
{ config, lib, ... }:
with lib;
let
cfg = homelab.services.paperless;
homelab = config.homelab;
service = "paperless";
in
{
options.homelab.services.${service} = {
enable = mkEnableOption "Enable ${service}";
url = mkOption {
default = "${service}.${homelab.domain}";
type = types.str;
};
homepage.name = mkOption {
default = "Paperless-ngx";
type = types.str;
};
homepage.description = mkOption {
default = "Document management system";
type = types.str;
};
homepage.icon = mkOption {
default = "paperless";
type = types.str;
};
homepage.category = mkOption {
default = "Services";
type = types.str;
};
};
config = mkIf cfg.enable {
services = {
${service} = {
enable = true;
dataDir = "/mnt/media/${service}";
domain = "https://${cfg.url}";
};
nginx.virtualHosts."${cfg.url}" = {
forceSSL = true;
useACMEHost = homelab.domain;
locations."/" = {
proxyPass = "http://localhost:${toString config.services.${service}.port}";
recommendedProxySettings = true;
};
};
};
};
}

View file

@ -1,88 +0,0 @@
{
config,
inputs,
lib,
...
}:
let
inherit (lib)
mkEnableOption
mkIf
mkOption
types
;
cfg = homelab.services.${service};
homelab = config.homelab;
service = "peertube";
in
{
options.homelab.services.${service} = {
enable = mkEnableOption "Enable ${service}";
url = mkOption {
default = "videos.${homelab.domain}";
type = types.str;
};
homepage.name = mkOption {
default = "Peertube";
type = types.str;
};
homepage.description = mkOption {
default = "A free and open-source, decentralized, ActivityPub federated video platform";
type = types.str;
};
homepage.icon = mkOption {
default = "peertube";
type = types.str;
};
homepage.category = mkOption {
default = "Media";
type = types.str;
};
};
config = mkIf cfg.enable {
services = {
${service} = {
enable = true;
configureNginx = true;
enableWebHttps = false;
localDomain = cfg.url;
database = {
createLocally = true;
};
redis = {
createLocally = true;
enableUnixSocket = true;
};
secrets.secretsFile = config.age.secrets.peertube-env.path;
settings = {
webserver = {
hostname = config.services.${service}.localDomain;
port = lib.mkForce 443;
};
};
};
cloudflared.tunnels.${homelab.cloudflared.tunnelId}.ingress = {
${cfg.url} = "http://localhost:${toString config.services.${service}.listenWeb}";
};
};
age.secrets."${service}-env" = {
file = "${inputs.self}/secrets/${service}-env.age";
owner = config.services.${service}.user;
};
};
}

View file

@ -1,38 +0,0 @@
{ lib, ... }:
let
inherit (lib) mkOption types;
in
{
options.homelab.ports = mkOption {
internal = true;
type = types.attrsOf types.port;
};
config.homelab.ports = {
homepage-dashboard = 8097;
mealie = 9001;
pihole = 8082;
tubearchivist = 8099;
vaultwarden = 8022;
nginx-website-sculpin = 8095;
nginx-website-tome = 8098;
nginx-books = 9002;
nginx-bootstrap-with-tailwind = 8081;
nginx-eric = 8084;
nginx-examples = 9003;
nginx-florida-drupalcamp-tailwind-css = 8083;
nginx-luke = 8094;
nginx-phpsw-sculpin-demo = 8085;
nginx-rebuilding-acquia = 8086;
nginx-rebuilding-bartik = 8087;
nginx-rebuilding-bristol-js = 8088;
nginx-rebuilding-symfony = 8089;
nginx-tailwindcss-demo = 8090;
nginx-talking-drupal-tailwindcss = 8093;
nginx-wp-tailwind = 8091;
nginx-zet = 8092;
};
}

View file

@ -1,6 +0,0 @@
{
age.secrets = {
cloudflare.file = ../../secrets/cloudflare.age;
cloudflared.file = ../../secrets/cloudflared-credentials.age;
};
}

View file

@ -1,5 +0,0 @@
{
imports = [
./tubearchivist.nix
];
}

View file

@ -1,50 +0,0 @@
{
config,
inputs,
pkgs,
...
}:
{
imports = [
./homepage
./mastodon.nix
./mealie.nix
./samba.nix
./uptime-kuma.nix
./vaultwarden.nix
];
services = {
postgresqlBackup.enable = true;
};
services.gitea-actions-runner.instances.default = {
enable = true;
hostPackages = with pkgs; [
bash
coreutils
curl
gawk
gitMinimal
gnused
jq
nix
nodejs
wget
];
labels = [
"nixos:host"
];
name = config.networking.hostName;
tokenFile = config.age.secrets.forgejo-runner-token.path;
url = config.services.forgejo.settings.server.ROOT_URL;
};
age.secrets = {
forgejo-runner-token.file = "${inputs.self}/secrets/forgejo-runner-token.age";
};
}

View file

@ -1,63 +0,0 @@
{ config, lib, ... }:
with lib;
let
cfg = homelab.services.${service};
homelab = config.homelab;
service = "homepage-dashboard";
in
{
options.homelab.services.${service} = {
enable = mkEnableOption "Enable ${service}";
url = mkOption {
default = "${config.networking.hostName}.${homelab.domain}";
type = types.str;
};
};
config = mkIf cfg.enable {
services = {
${service} = {
enable = true;
listenPort = homelab.ports.${service};
openFirewall = true;
customCSS = ''
#information-widgets {
padding-left: 1.5rem;
padding-right: 1.5rem;
}
div#footer {
display: none;
}
.services-group {
margin-bottom: 3rem;
}
'';
services = (import ./services.nix { inherit config lib; });
settings = {
headerStyle = "clean";
hideVersion = "true";
layout = (import ./layout.nix);
statusStyle = "dot";
};
};
glances.enable = true;
nginx.virtualHosts.${cfg.url} = {
forceSSL = true;
useACMEHost = homelab.domain;
locations."/".proxyPass =
"http://localhost:${toString config.services.homepage-dashboard.listenPort}";
};
};
};
}

View file

@ -1,57 +0,0 @@
{ config }:
{
Glances =
let
port = toString config.services.glances.port;
in
[
{
Info = {
widget = {
type = "glances";
url = "http://localhost:${port}";
metric = "info";
chart = false;
version = 4;
};
};
}
{
"CPU Temp" = {
widget = {
type = "glances";
url = "http://localhost:${port}";
metric = "sensor:Package id 0";
chart = false;
version = 4;
};
};
}
{
Processes = {
widget = {
type = "glances";
url = "http://localhost:${port}";
metric = "process";
chart = false;
version = 4;
};
};
}
{
Network = {
widget = {
type = "glances";
url = "http://localhost:${port}";
metric = "network:enp0s20f0u1";
chart = false;
version = 4;
};
};
}
];
}

View file

@ -1,23 +0,0 @@
[
{
Glances = {
columns = 4;
header = false;
style = "row";
};
}
{
Media = {
header = true;
style = "column";
};
}
{
Services = {
header = true;
style = "column";
};
}
]

View file

@ -1,32 +0,0 @@
{ config, lib }:
with lib;
let
homelab = config.homelab.services;
homepageCategories = [
"Media"
"Services"
];
homepageServices =
category:
(attrsets.filterAttrs (
name: value: value ? homepage && value.homepage.category == category
) homelab);
services = lists.forEach homepageCategories (cat: {
"${cat}" =
lib.lists.forEach (lib.attrsets.mapAttrsToList (name: value: name) (homepageServices "${cat}"))
(x: {
"${homelab.${x}.homepage.name}" = {
icon = homelab.${x}.homepage.icon;
description = homelab.${x}.homepage.description;
href = "https://${homelab.${x}.url}";
siteMonitor = "https://${homelab.${x}.url}";
};
});
});
in
services ++ [ (import ./glances.nix { inherit config; }) ]

View file

@ -1,84 +0,0 @@
{ config, lib, ... }:
with lib;
let
cfg = config.homelab.services.${service};
domain = "oliverdavies.uk";
service = "mastodon";
in
{
options.homelab.services.${service} = {
url = mkOption {
default = "social.${domain}";
internal = true;
type = types.str;
};
};
config = {
services = {
${service} = {
enable = false;
configureNginx = false;
localDomain = domain;
streamingProcesses = 3;
extraConfig = {
SINGLE_USER_MODE = "true";
WEB_DOMAIN = cfg.url;
};
smtp = {
fromAddress = "social@${domain}";
};
};
cloudflared.tunnels.${config.homelab.cloudflared.tunnelId} = {
ingress = {
"${cfg.url}" = "http://localhost";
};
};
nginx = {
upstreams.mastodon-streaming = {
extraConfig = ''
least_conn;
'';
servers = builtins.listToAttrs (
map (i: {
name = "unix:/run/mastodon-streaming/streaming-${toString i}.socket";
value = { };
}) (range 1 config.services.mastodon.streamingProcesses)
);
};
virtualHosts."social.oliverdavies.uk" = {
root = "${config.services.mastodon.package}/public/";
locations = {
"/".tryFiles = "$uri @proxy";
"/api/v1/streaming/" = {
proxyPass = "http://mastodon-streaming";
proxyWebsockets = true;
};
"/system/".alias = "/var/lib/mastodon/public-system/";
"@proxy" = {
proxyPass = "http://unix:/run/mastodon-web/web.socket";
proxyWebsockets = true;
};
};
extraConfig = ''
client_max_body_size 100m;
'';
};
};
};
};
}

View file

@ -1,27 +0,0 @@
{ config, pkgs, ... }:
let
ports = config.homelab.ports;
in
{
services.mealie = {
enable = true;
package = pkgs.stable.mealie;
database.createLocally = true;
port = ports.mealie;
settings.ALLOW_SIGNUP = "false";
};
services.nginx.virtualHosts."mealie.oliverdavies.uk" = {
forceSSL = true;
useACMEHost = "oliverdavies.uk";
locations."/" = {
proxyPass = "http://localhost:${toString config.services.mealie.port}";
recommendedProxySettings = true;
};
};
}

View file

@ -1,28 +0,0 @@
{
services.samba = {
enable = true;
openFirewall = true;
settings = {
home = {
path = "/home/opdavies";
browseable = true;
writable = true;
"valid users" = [ "opdavies" ];
"force group" = "media";
"create mask" = "0660";
"directory mask" = "0770";
};
media = {
path = "/mnt/media";
browseable = true;
writable = true;
"valid users" = [ "opdavies" ];
"force group" = "media";
"create mask" = "0660";
"directory mask" = "0770";
};
};
};
}

View file

@ -1,55 +0,0 @@
{ config, lib, ... }:
with lib;
let
cfg = homelab.services.${service};
homelab = config.homelab;
service = "uptime-kuma";
in
{
options.homelab.services.${service} = {
enable = mkEnableOption "Enable ${service}";
url = mkOption {
default = "uptime.${homelab.domain}";
type = types.str;
};
homepage.name = mkOption {
default = "Uptime Kuma";
type = types.str;
};
homepage.description = mkOption {
default = "A fancy self-hosted monitoring tool";
type = types.str;
};
homepage.icon = mkOption {
default = "uptime-kuma";
type = types.str;
};
homepage.category = mkOption {
default = "Services";
type = types.str;
};
};
config = mkIf cfg.enable {
services = {
${service}.enable = true;
nginx.virtualHosts.${cfg.url} = {
forceSSL = true;
useACMEHost = homelab.domain;
locations."/" = {
proxyPass = "http://localhost:${toString config.services.${service}.settings.PORT}";
recommendedProxySettings = true;
};
};
};
};
}

View file

@ -1,53 +0,0 @@
{
config,
inputs,
lib,
...
}:
with lib;
let
cfg = homelab.services.${service};
homelab = config.homelab;
service = "vaultwarden";
in
{
options.homelab.services.${service} = {
enable = mkEnableOption "Enable ${service}";
url = mkOption {
default = "${service}.${homelab.domain}";
type = types.str;
};
};
config = mkIf cfg.enable {
services = {
${service} = {
enable = true;
environmentFile = config.age.secrets.vaultwarden-env.path;
config = {
DOMAIN = "https://${cfg.url}";
ROCKET_ADDRESS = "127.0.0.1";
ROCKET_PORT = homelab.ports.${service};
SIGNUPS_ALLOWED = false;
};
};
nginx.virtualHosts.${cfg.url} = {
forceSSL = true;
useACMEHost = homelab.domain;
locations."/" = {
proxyPass = "http://localhost:${toString config.services.${service}.config.ROCKET_PORT}";
recommendedProxySettings = true;
};
};
};
age.secrets.vaultwarden-env.file = "${inputs.self}/secrets/vaultwarden-env.age";
};
}

View file

@ -1,98 +0,0 @@
{ inputs, pkgs, ... }:
{
imports = [
inputs.agenix.nixosModules.default
inputs.nixos-hardware.nixosModules.common-gpu-intel
inputs.nixos-hardware.nixosModules.lenovo-thinkpad-t480
../common
./hardware-configuration.nix
./cron.nix
./neomutt.nix
./newsboat
./secrets.nix
./xserver.nix
../../users/opdavies.nix
];
services = {
auto-cpufreq.enable = true;
geoclue2.enable = true;
gvfs.enable = true;
power-profiles-daemon.enable = false;
printing.enable = true;
pulseaudio.enable = false;
thermald.enable = true;
throttled.enable = true;
upower.enable = true;
};
boot = {
loader = {
systemd-boot.enable = true;
systemd-boot.configurationLimit = 10;
efi.canTouchEfiVariables = true;
};
};
systemd.settings.Manager = {
DefaultTimeoutStopSec = "10s";
};
networking.networkmanager.enable = true;
networking.hosts = {
"192.168.1.116" = [
"home.oliverdavies.uk"
"jellyfin.oliverdavies.uk"
"nixedo.oliverdavies.uk"
"paperless.oliverdavies.uk"
"photos.oliverdavies.uk"
"ssh.oliverdavies.uk"
"tubearchivist.oliverdavies.uk"
];
};
security = {
polkit.enable = true;
rtkit.enable = true;
};
environment.systemPackages = with pkgs; [
abook
acpi
arandr
brightnessctl
cdrkit
cpufrequtils
dvdbackup
dvdplusrwtools
ffmpegthumbnailer
gimp3
gtypist
hunspellDicts.en-gb-large
isync
kdePackages.kdenlive
kdePackages.okular
libnotify
libreoffice
meslo-lg
obs-studio
pam_gnupg
pamixer
pavucontrol
peek
pmutils
shotwell
stable.gscan2pdf
sxiv
ttyper
xcape
xsel
yt-dlp
];
}

View file

@ -1,12 +0,0 @@
{ pkgs, ... }:
{
services.cron = {
enable = true;
systemCronJobs = [
"*/15 * * * * opdavies ${pkgs.imapfilter}/bin/imapfilter -c ~/Code/personal/email-filters/config.lua"
"0 8,20 * * * opdavies ${pkgs.isync}/bin/mbsync -a"
];
};
}

View file

@ -1,53 +0,0 @@
# 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"
"usb_storage"
"sd_mod"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
fileSystems."/" = {
device = "/dev/disk/by-uuid/34bd5f2e-8ccf-4d5f-876c-9d7ea84c44f0";
fsType = "ext4";
};
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/B8BC-688D";
fsType = "vfat";
options = [
"fmask=0077"
"dmask=0077"
];
};
swapDevices = [ ];
# 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
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
networking.useDHCP = lib.mkDefault true;
# networking.interfaces.enp0s31f6.useDHCP = lib.mkDefault true;
# networking.interfaces.wlp3s0.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

View file

@ -1,7 +0,0 @@
{
home-manager.users.opdavies.programs.neomutt = {
enable = true;
vimKeys = true;
};
}

View file

@ -1,30 +0,0 @@
{
home-manager.users.opdavies.programs.newsboat = {
enable = true;
extraConfig = ''
bind-key j down
bind-key k up
bind-key j next articlelist
bind-key k prev articlelist
bind-key J next-feed articlelist
bind-key K prev-feed articlelist
bind-key g home
bind-key G end
bind-key d pagedown
bind-key u pageup
bind-key a toggle-article-read
bind-key n next-unread
bind-key N prev-unread
bind-key x pb-delete
color info white black bold
'';
urls = import ./urls.nix;
};
}

View file

@ -1,298 +0,0 @@
[
{ url = "https://www.reddit.com/r/nginx/new/.rss"; }
{ url = "https://www.reddit.com/r/devops/.rss"; }
{ url = "https://medium.com/feed/@bdfinst"; }
{ url = "https://blog.system76.com/rss"; }
{ url = "https://medium.com/feed/@codemonkeymike"; }
{ url = "https://www.reddit.com/r/devops/new/.rss"; }
{ url = "https://www.reddit.com/r/sysadmin/.rss"; }
{
url = "https://www.carlpullein.com/blog?format=RSS";
title = "Carl Pullein";
tags = [ "Productivity" ];
}
{ url = "https://feeds.feedburner.com/Faildesk"; }
{ url = "https://syndication.thedailywtf.com/TheDailyWtf"; }
{ url = "https://www.sherdog.com/rss/videos2.xml"; }
{
url = "https://www.reddit.com/r/MMA/.rss";
tags = [ "MMA" ];
}
{
url = "https://mmaweekly.com/feed/rss";
tags = [ "MMA" ];
}
{
url = "https://www.sherdog.com/rss/news2.xml";
tags = [ "MMA" ];
}
{
url = "https://www.sherdog.com/rss/articles2.xml";
tags = [ "MMA" ];
}
{
url = "https://www.ufc.com/rss/news";
tags = [ "MMA" ];
}
{ url = "https://www.theregister.co.uk/headlines.atom"; }
{
url = "https://www.rbs6nations.com/en/RssLatestNews.xml";
tags = [ "Rugby" ];
}
{
url = "https://feeds.feedburner.com/rugbydump";
tags = [ "Rugby" ];
}
{
url = "https://www.telegraph.co.uk/sport/rugbyunion/rss";
tags = [ "Rugby" ];
}
{ url = "https://code.facebook.com/posts/rss"; }
{ url = "https://nginx.com/feed/rss"; }
{
url = "https://www.lornajane.net/feed";
tags = [ "Software" ];
}
{
url = "https://nginx.org/index.rss";
tags = [ "Software" ];
}
{ url = "https://www.engadget.com/rss.xml"; }
{ url = "https://rss.slashdot.org/Slashdot/slashdotIt"; }
{ url = "https://lwn.net/headlines/newrss"; }
{ url = "https://rss.slashdot.org/Slashdot/slashdotLinux"; }
{
url = "https://blog.sebastian-daschner.com/feeds/rss";
title = "Sebastian Daschner";
}
{ url = "https://www.reddit.com/r/linux/.rss"; }
{ url = "https://githubengineering.com/atom.xml"; }
{ url = "https://rss.slashdot.org/Slashdot/slashdotDevelopers"; }
{ url = "https://www.alistapart.com/rss.xml"; }
{ url = "https://www.christitus.com/index.xml"; }
{ url = "https://www.freeagentcentral.com/feed.rss"; }
{ url = "https://akrabat.com/feed Software"; }
{ url = "https://jasonmccreary.me/feed.atom"; }
{ url = "https://martinfowler.com/bliki/bliki.atom"; }
{ url = "https://lornajane.net/feed"; }
{ url = "https://christoph-rumpel.com/feed.xml"; }
{ url = "https://gdstechnology.blog.gov.uk/feed/atom"; }
{ url = "https://weierophinney.net/matthew/feeds/index.rss2"; }
{ url = "https://stitcher.io/rss"; }
{ url = "https://www.reddit.com/r/css.rss"; }
{ url = "https://www.reddit.com/r/PHP/.rss"; }
{ url = "https://whateverthing.com/atom.xml"; }
{ url = "https://mnapoli.fr/atom.xml"; }
{ url = "https://www.epicweb.dev/rss.xml?ck_subscriber_id=2498091571"; }
{ url = "https://dev.to/feed"; }
{ url = "https://localheinz.com/feed.xml"; }
{ url = "https://www.ben-morris.com/feed"; }
{ url = "https://www.jbrains.ca/rss"; }
{ url = "https://blog.thecodewhisperer.com/rss"; }
{ url = "https://odan.github.io/feed.xml"; }
{ url = "https://feeds.feedburner.com/symfony/blog"; }
{ url = "https://www.alwaysagileconsulting.com/feed"; }
{ url = "https://blog.sensiolabs.com/feed"; }
{ url = "https://pascalbaljetmedia.com/rss"; }
{ url = "https://tighten.co/blog/feed.atom"; }
{ url = "https://ryangjchandler.co.uk/feed"; }
{ url = "https://jnsgr.uk/posts/index.xml"; }
{ url = "https://timacdonald.me/feed.xml"; }
{ url = "https://phppot.com/feed"; }
{ url = "https://howtocodewell.libsyn.com/rss"; }
{ url = "https://ctankersley.com/atom.xml"; }
{ url = "https://blog.wyrihaximus.net/atom.xml"; }
{ url = "https://dotfyle.com/this-week-in-neovim/rss.xml"; }
{ url = "https://paul-m-jones.com/feed"; }
{ url = "https://www.tomasvotruba.cz/rss.xml"; }
{ url = "https://www.reddit.com/r/git/.rss"; }
{ url = "https://www.daveismyname.com/feed"; }
{
url = "https://murze.be/feed/php";
title = "freek.dev";
tags = [
"PHP"
"Laravel"
"Software"
];
}
{ url = "https://nikic.github.io/rss.xml"; }
{
url = "https://drupal.org/planet/rss.xml";
tags = [ "Drupal" ];
}
{ url = "https://www.bram.us/feed"; }
{ url = "https://feeds.feedburner.com/GiantRobotsSmashingIntoOtherGiantRobots"; }
{ url = "https://murze.be/feed/originals"; }
{ url = "https://www.patkua.com/feed"; }
{ url = "https://www.benjystanton.co.uk/feed.xml"; }
{
url = "https://drupal.org/security/rss.xml";
tags = [ "Drupal" ];
}
{
url = "https://uk.indeed.com/rss?q=symfony&l=np18";
tags = [ "Jobs" ];
}
{
url = "https://uk.indeed.com/rss?q=php&l=np18";
tags = [ "Jobs" ];
}
{
url = "https://jobs.drupal.org/all-jobs/feed";
tags = [ "Jobs" ];
}
{
url = "https://www.reed.co.uk/jobs/rss/np18?source=rss&keywords=drupal&salaryfrom=50000&sortby=DisplayDate";
tags = [ "Jobs" ];
}
{
url = "https://www.reed.co.uk/jobs/rss/np18?source=rss&keywords=php&salaryfrom=50000&sortby=DisplayDate";
tags = [ "Jobs" ];
}
{
url = "https://uk.indeed.com/rss?q=drupal&l=np18";
tags = [ "Jobs" ];
}
{
url = "https://www.reed.co.uk/jobs/rss/np18?source=rss&keywords=symfony&salaryfrom=50000&sortby=DisplayDate";
tags = [ "Jobs" ];
}
{ url = "https://emilywebber.co.uk/feed"; }
{ url = "https://introvertdear.com/feed"; }
{ url = "https://designli.co/blog/feed"; }
{ url = "https://www.oliverdavies.uk/rss/daily.xml"; }
{
url = "https://www.drupal.org/project/issues/rss/override_node_options";
tags = [ "Drupal" ];
}
{
url = "https://www.drupal.org/project/issues/rss/tailwindcss";
tags = [ "Drupal" ];
}
{
url = "https://nixos.org/blog/announcements-rss.xml";
tags = [ "Linux" ];
}
{
url = "https://laracasts.com/feed";
tags = [
"PHP"
"Laravel"
];
}
{
url = "https://feeds.feedburner.com/knpuniversity";
title = "SymfonyCasts";
tags = [
"PHP"
"Symfony"
];
}
{
url = "https://nickjanetakis.com/atom.xml";
title = "Nick Janetakis";
}
{
url = "https://www.learnlinux.tv/feed";
tags = [ "Linux" ];
}
{
url = "https://tailwindcss.com/feeds/feed.xml";
tags = [
"Software"
"CSS"
];
}
{
url = "https://monospacementor.com/feed";
tags = [
"Linux"
"Software"
];
}
{
url = "https://frontendmasters.com/blog/feed";
tags = [ "Software" ];
title = "Frontend Masters Boost";
}
{
url = "https://www.youtube.com/feeds/videos.xml?channel_id=UC2aHRY064THg_t7JZoGSYGg";
title = "YouTube - elysse";
tags = [
"Software"
"YouTube"
];
}
{
url = "https://www.youtube.com/feeds/videos.xml?channel_id=UCSUA5RARrNt4-Ik3qtbETLQ";
title = "YouTube - Jason Swett";
tags = [
"Software"
"YouTube"
];
}
{
url = "https://www.youtube.com/feeds/videos.xml?channel_id=UCorzANoC3fX9VVefJHM5wtA";
title = "~YouTube - Nick Janetakis";
tags = [
"Software"
"YouTube"
];
}
{ url = "https://devenv.sh/feed_rss_created.xml"; }
{ url = "https://sive.rs/en.atom"; }
{ url = "https://kressle.in/feed.xml"; }
{
url = "https://github.com/sculpin/sculpin/releases.atom";
tags = [
"PHP"
"Sculpin"
"Open Source"
];
}
{ url = "https://www.theminimalists.com/feed"; }
{ url = "https://opensourcepledge.com/rss.xml"; }
{
url = "https://feeds.bbci.co.uk/sport/rugby-union/teams/ng-dragons/rss.xml";
tags = [ "Rugby" ];
title = "BBC Sport - Dragons RFC";
}
{
url = "https://openrss.org/www.twitch.tv/thealtf4stream/videos?filter=all&sort=time";
tags = [ "Twitch" ];
}
{
url = "https://openrss.org/www.twitch.tv/theprimeagen/videos?filter=all&sort=time";
tags = [ "Twitch" ];
}
{
url = "https://openrss.org/www.twitch.tv/teej_dv/videos?filter=all&sort=time";
tags = [ "Twitch" ];
}
{
url = "https://openrss.org/www.twitch.tv/monospacementor/videos?filter=all&sort=time";
tags = [ "Twitch" ];
}
{ url = "https://www.reddit.com/r/librewolf/new/.rss"; }
{
url = "https://www.youtube.com/feeds/videos.xml?channel_id=UCSJKQnpmPcdkysduL0mNktg";
title = "YouTube - teej_daily";
tags = [
"Software"
"YouTube"
];
}
{
url = "https://feeds.bbci.co.uk/sport/rugby-union/rss.xml";
tags = [ "Rugby" ];
title = "BBC Sport - Rugby Union";
}
{ url = "https://tinkerbetter.tube/feeds/videos.xml?videoChannelId=2"; }
{ url = "https://video.fosshq.org/feeds/videos.xml?videoChannelId=2"; }
{
url = "https://www.garfieldtech.com/blog/feed";
tags = [ "PHP" ];
}
{ url = "https://world.hey.com/dhh/feed.atom"; }
]

View file

@ -1,5 +0,0 @@
{
age.secrets = {
cloudflare.file = ../../secrets/cloudflare.age;
};
}

View file

@ -1,12 +0,0 @@
{
services.xserver = {
enable = true;
displayManager.startx.enable = true;
xkb = {
layout = "gb";
variant = "";
};
};
}

View file

@ -1,35 +0,0 @@
alias b := build
alias s := switch
alias t := test
alias u := update
_default:
just --list
build *args:
@just _nixos build {{ args }}
check:
nix flake check
clean:
nh clean all
collect-garbage:
nix-collect-garbage -d
sudo nix-collect-garbage -d
format:
nix fmt flake.nix hosts modules
switch *args:
@just _nixos switch {{ args }}
test *args:
@just _nixos test {{ args }}
update:
nix flake update --commit-lock-file
_nixos command *args:
nh os {{ command }} . {{ args }}

23
main.yaml Normal file
View file

@ -0,0 +1,23 @@
---
- hosts: localhost
tasks:
- name: Set roles
ansible.builtin.set_fact:
roles: "{{ ansible_run_tags != ['all'] and ansible_run_tags or default_roles | difference(exclude_roles | default([])) }}"
tags:
- always
- name: Display roles
ansible.builtin.debug: "var=roles"
tags:
- always
- name: Run roles
ansible.builtin.include_role:
name: "{{ item }}"
apply:
tags:
- "{{ item }}"
with_items: "{{ roles }}"
tags:
- always

View file

View file

@ -1,12 +0,0 @@
{
flake.modules.nixos.pc.services.avahi = {
enable = true;
nssmdns4 = true;
openFirewall = true;
publish = {
enable = true;
addresses = true;
};
};
}

View file

@ -1,7 +0,0 @@
{
flake.modules.nixos.desktop = {
hardware.bluetooth.enable = true;
services.blueman.enable = true;
};
}

View file

@ -1,29 +0,0 @@
{
flake.modules.homeManager.base =
{ pkgs, ... }:
{
home.packages = [
pkgs.bluetuith
];
xdg.configFile."bluetuith/bluetuith.conf" = {
text = ''
{
adapter: ""
adapter-states: ""
connect-bdaddr: ""
gsm-apn: ""
gsm-number: ""
keybindings: {
NavigateDown: j
NavigateUp: k
}
receive-dir: ""
theme: {}
}
'';
};
};
}

View file

@ -1,57 +0,0 @@
{ lib, ... }:
{
flake.modules.homeManager.gui =
{ config, pkgs, ... }:
{
options.programs.bookmarkthis.snippetsFile = lib.mkOption {
default = "${config.xdg.dataHome}/snippets.txt";
type = lib.types.str;
};
config = {
home = {
packages = [
(pkgs.writeShellApplication {
name = "bookmarkthis";
text = ''
message() {
if command -v ${lib.getExe pkgs.libnotify} > /dev/null; then
${lib.getExe pkgs.libnotify} "$1" "$2"
else
echo "$2"
fi
}
main() {
bookmark="$(xclip -o)"
file="$SNIPPETS_FILE"
if grep -q "^$bookmark$" "$file"; then
message "Oops." "Already bookmarked." >&2
exit 2
fi
echo "$bookmark" >> "$file"
message "Bookmark added!" "$bookmark is now saved to the file."
}
main
'';
})
];
sessionVariables = {
SNIPPETS_FILE = config.programs.bookmarkthis.snippetsFile;
};
};
programs.zsh.zsh-abbr.abbreviations = lib.optionalAttrs (config.programs.zsh.enable) {
"sn" = "${config.home.sessionVariables.EDITOR} $SNIPPETS_FILE";
};
};
};
}

View file

@ -1,3 +0,0 @@
{
flake.modules.homeManager.gui.programs.chromium.enable = true;
}

View file

@ -1,3 +0,0 @@
{
flake.modules.homeManager.gui.programs.librewolf.enable = true;
}

View file

@ -1,17 +0,0 @@
{
flake.modules.homeManager.gui =
{ pkgs, ... }:
{
programs.librewolf.profiles.default.extensions.packages =
with pkgs.nur.repos.rycee.firefox-addons; [
awesome-rss
bitwarden
darkreader
tree-style-tab
ublock-origin
videospeed
vimium
web-developer
];
};
}

View file

@ -1,5 +0,0 @@
{
flake.modules.homeManager.gui.programs.librewolf.languagePacks = [
"en-GB"
];
}

View file

@ -1,70 +0,0 @@
{
flake.modules.homeManager.gui.programs.librewolf.policies = {
CaptivePortal = false;
DisableFirefoxAccounts = true;
DisableFirefoxStudies = true;
DisablePocket = true;
DisableTelemetry = true;
EnableTrackingProtection = {
Cryptomining = true;
Fingerprinting = true;
Value = true;
};
ExtensionSettings = {
"jid1-ZAdIEUB7XOzOJw@jetpack" = {
install_url = "https://addons.mozilla.org/firefox/downloads/latest/duckduckgo-for-firefox/latest.xpi";
installation_mode = "force_installed";
};
"uBlock0@raymondhill.net" = {
install_url = "https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi";
installation_mode = "force_installed";
};
};
FirefoxHome = {
Highlights = false;
Pocket = false;
Search = true;
Snippets = false;
SponsoredPocket = false;
SponsoredTopSites = false;
TopSites = true;
};
FirefoxSuggest = {
ImproveSuggest = false;
SponsoredSuggestions = false;
WebSuggestions = false;
};
NoDefaultBookmarks = true;
OfferToSaveLogins = false;
OfferToSaveLoginsDefault = false;
PasswordManagerEnabled = false;
Preferences = {
"browser.newtabpage.enabled" = false;
"cookiebanners.service.mode" = 2; # Block cookie banners
"cookiebanners.service.mode.privateBrowsing" = 2; # Block cookie banners in private browsing
"privacy.donottrackheader.enabled" = true;
"privacy.fingerprintingProtection" = true;
"privacy.resistFingerprinting" = true;
"privacy.trackingprotection.emailtracking.enabled" = true;
"privacy.trackingprotection.enabled" = true;
"privacy.trackingprotection.fingerprinting.enabled" = true;
"privacy.trackingprotection.socialtracking.enabled" = true;
};
HardwareAcceleration = true;
TranslateEnabled = true;
UserMessaging = {
ExtensionRecommendations = false;
UrlbarInterventions = false;
SkipOnboarding = true;
};
};
}

View file

@ -1,19 +0,0 @@
{
flake.modules.homeManager.gui.programs.librewolf.profiles.default.search.engines = {
# TODO: Drupal.org users.
# TODO: Mastodon.
# TODO: GitHub.
# TODO: Forgejo.
drupal_projects = {
name = "Drupal.org projects";
urls = [ { template = "https://www.drupal.org/project/{searchTerms}"; } ];
definedAliases = [ "@dp" ];
};
nixvim = {
name = "Nixvim options search";
urls = [ { template = "https://nix-community.github.io/nixvim/search/?query={searchTerms}"; } ];
definedAliases = [ "@nxv" ];
};
};
}

View file

@ -1,7 +0,0 @@
{
flake.modules.homeManager.gui.programs.librewolf.profiles.default.search = {
default = "ddg";
force = true;
privateDefault = "ddg";
};
}

View file

@ -1,10 +0,0 @@
{
flake.modules.homeManager.gui.programs.librewolf.profiles.default.settings = {
"browser.search.isUS" = false;
"browser.search.region" = "GB";
"distribution.searchplugins.defaultLocale" = "en-GB";
"general.useragent.locale" = "en-GB";
"intl.accept_languages" = "en-GB, en";
"intl.regional_prefs.use_os_locales" = true;
};
}

View file

@ -1,3 +0,0 @@
{
flake.modules.homeManager.gui.programs.qutebrowser.enable = true;
}

View file

@ -1,14 +0,0 @@
{ lib, ... }:
{
flake.modules.homeManager.gui.programs.qutebrowser.keyBindings.normal = {
"<Ctrl-d>" = "config-cycle colors.webpage.darkmode.enabled true false";
"xb" = "config-cycle statusbar.show always never";
"xt" = "config-cycle tabs.show always never";
"xx" = lib.mkMerge [
"config-cycle statusbar.show always never"
"config-cycle tabs.show always never"
];
};
}

View file

@ -1,7 +0,0 @@
{
flake.modules.homeManager.gui =
{ pkgs, ... }:
{
programs.qutebrowser.package = pkgs.stable.qutebrowser;
};
}

View file

@ -1,10 +0,0 @@
{
flake.modules.homeManager.gui.programs.qutebrowser.searchEngines = {
dp = "https://www.drupal.org/project/{}";
du = "https://www.drupal.org/u/{}";
gh = "https://github.com/search?q={}";
mn = "https://mynixos.com/search?q={}";
nx = "https://search.nixos.org/packages?query={}";
yt = "https://www.youtube.com/results?search_query={}";
};
}

View file

@ -1,5 +0,0 @@
{
flake.modules.homeManager.gui.programs.qutebrowser.settings = {
colors.webpage.darkmode.enabled = true;
};
}

View file

@ -1,7 +0,0 @@
{
flake.modules.nixos.pc =
{ pkgs, ... }:
{
environment.systemPackages = [ pkgs.bc ];
};
}

Some files were not shown because too many files have changed in this diff Show more