Compare commits
No commits in common. "fc68d313b1d7e4f016b04463b9258d48c09f9793" and "bd5737ad7aa9c4842bb7d46f199b305a2a1f8386" have entirely different histories.
fc68d313b1
...
bd5737ad7a
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,2 @@
|
|||||||
.direnv
|
.direnv
|
||||||
tmp/
|
tmp/
|
||||||
nixos.qcow2
|
|
||||||
|
7
Makefile
7
Makefile
@ -1,4 +1,4 @@
|
|||||||
.PHONY: help serve test-data demo
|
.PHONY: help serve test-data
|
||||||
|
|
||||||
help: ## display this help
|
help: ## display this help
|
||||||
@awk 'BEGIN{FS = ":.*##"; printf "\033[1m\nUsage\n \033[1;92m make\033[0;36m <target>\033[0m\n"} /^[a-zA-Z0-9_-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } ' $(MAKEFILE_LIST)
|
@awk 'BEGIN{FS = ":.*##"; printf "\033[1m\nUsage\n \033[1;92m make\033[0;36m <target>\033[0m\n"} /^[a-zA-Z0-9_-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } ' $(MAKEFILE_LIST)
|
||||||
@ -7,7 +7,4 @@ serve: ## Run "intake serve" with live reload
|
|||||||
@air -build.cmd "go build -o tmp/intake" -build.bin tmp/intake -build.args_bin serve,--data-dir,tmp -build.include_ext "go,html,css"
|
@air -build.cmd "go build -o tmp/intake" -build.bin tmp/intake -build.args_bin serve,--data-dir,tmp -build.include_ext "go,html,css"
|
||||||
|
|
||||||
test-data: ## Recreate test data in tmp/
|
test-data: ## Recreate test data in tmp/
|
||||||
@test/test_items.sh
|
@test/test_items.sh
|
||||||
|
|
||||||
demo: ## Run the demo vm
|
|
||||||
@nix run ".#nixosConfigurations.demo.config.system.build.nixos-shell"
|
|
26
README.md
26
README.md
@ -4,8 +4,6 @@ Intake is an arbitrary feed aggregator that generalizes the concept of a feed.
|
|||||||
Rather than being restricted to parsing items out of an RSS feed, Intake provides a middle layer of executing arbitrary commands that conform to a JSON-based specification.
|
Rather than being restricted to parsing items out of an RSS feed, Intake provides a middle layer of executing arbitrary commands that conform to a JSON-based specification.
|
||||||
An Intake source can parse an RSS feed, but it can also scrape a website without a feed, provide additional logic to filter or annotate feed items, or integrate with an API.
|
An Intake source can parse an RSS feed, but it can also scrape a website without a feed, provide additional logic to filter or annotate feed items, or integrate with an API.
|
||||||
|
|
||||||
A demo running in a NixOS VM is available via `make demo` or using `nix run` on the `nixosConfigurations.demo.config.system.build.nixos-shell` flake attribute.
|
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
In Intake, a _source_ represents a single content feed of discrete _items_, such as a blog and its posts or a website and its pages.
|
In Intake, a _source_ represents a single content feed of discrete _items_, such as a blog and its posts or a website and its pages.
|
||||||
@ -105,20 +103,32 @@ Instead, the web interface can be locked behind a password set via `intake passw
|
|||||||
|
|
||||||
Parity features
|
Parity features
|
||||||
|
|
||||||
|
* [x] web feed supports item TTS
|
||||||
|
* [x] item punt
|
||||||
|
* [x] web feed paging
|
||||||
|
* [x] web fetch
|
||||||
|
* [x] crontab integration
|
||||||
* [ ] source batching
|
* [ ] source batching
|
||||||
* [x] NixOS module
|
* [x] add item from web
|
||||||
* [x] NixOS vm demo
|
* [x] web edit channels
|
||||||
|
* web edit sources
|
||||||
|
* [x] edit action argv
|
||||||
|
* [x] edit source envs
|
||||||
|
* [x] edit source crontab
|
||||||
|
* [x] Nix build
|
||||||
|
* [ ] NixOS module
|
||||||
|
* [ ] NixOS vm demo
|
||||||
|
|
||||||
Future features
|
Future features
|
||||||
|
|
||||||
* [ ] CLI simplification?
|
|
||||||
* [ ] on_delete triggers
|
* [ ] on_delete triggers
|
||||||
* [ ] manual item edits, CLI
|
* [ ] manual item edits, CLI
|
||||||
* [ ] manual item edits, web
|
* [ ] manual item edits, web
|
||||||
|
* [x] source-level TTS
|
||||||
* [ ] metric reporting
|
* [ ] metric reporting
|
||||||
|
* [x] on action failure, create an error item with logs
|
||||||
* [ ] items gracefully add new fields and `action` keys
|
* [ ] items gracefully add new fields and `action` keys
|
||||||
* [ ] arbitrary date punt
|
* [ ] arbitrary date punt
|
||||||
|
* [x] sort crontab entries
|
||||||
* [ ] TUI feed view
|
* [ ] TUI feed view
|
||||||
* Nix flake templates
|
* [ ] Nix flake templates
|
||||||
* [ ] parsing a news feed
|
|
||||||
* [ ] following a webcomic
|
|
||||||
|
@ -3,7 +3,6 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/Jaculabilis/intake/core"
|
"github.com/Jaculabilis/intake/core"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
@ -51,16 +50,4 @@ func sourceEnv(source string, env []string) {
|
|||||||
if err := core.SetEnvs(db, source, env); err != nil {
|
if err := core.SetEnvs(db, source, env); err != nil {
|
||||||
log.Fatalf("failed to set envs: %v", err)
|
log.Fatalf("failed to set envs: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, envval := range env {
|
|
||||||
if strings.HasPrefix(envval, "INTAKE_CRON=") {
|
|
||||||
specs, err := core.GetCronSources(db)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("failed to get cron specs: %v", err)
|
|
||||||
}
|
|
||||||
if err = core.UpdateCrontab(db, specs); err != nil {
|
|
||||||
log.Fatalf("failed to update crontab: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
if [ -f /home/alice/.intake-setup-done ]; then
|
|
||||||
echo "already done"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# intake service gets a crontab wrapper, cheat here
|
|
||||||
export PATH="/run/wrappers/bin:$PATH"
|
|
||||||
|
|
||||||
mkdir -p $INTAKE_DATA_DIR
|
|
||||||
|
|
||||||
intake source add -s echo
|
|
||||||
intake action add -s echo -a fetch -- jq -cn '{id: env.ID, title: env.MESSAGE}'
|
|
||||||
intake source env -s echo --set "ID=hello"
|
|
||||||
intake source env -s echo --set "MESSAGE=Hello, world!"
|
|
||||||
intake channel add -s echo -c home
|
|
||||||
|
|
||||||
intake source add -s currenttime
|
|
||||||
intake action add -s currenttime -a fetch -- sh -c "date +%Y-%m-%d-%H-%M | jq -cR '{id: .}'"
|
|
||||||
intake source env -s currenttime --set "INTAKE_CRON=* * * * *"
|
|
||||||
intake channel add -s currenttime -c home
|
|
||||||
|
|
||||||
touch /home/alice/.intake-setup-done
|
|
||||||
echo "done"
|
|
20
demo/bob.sh
20
demo/bob.sh
@ -1,20 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
if [ -f /home/bob/.intake-setup-done ]; then
|
|
||||||
echo "already done"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# intake service gets a crontab wrapper, cheat here
|
|
||||||
export PATH="/run/wrappers/bin:$PATH"
|
|
||||||
|
|
||||||
mkdir -p $INTAKE_DATA_DIR
|
|
||||||
|
|
||||||
intake source add -s echo
|
|
||||||
intake action add -s echo -a fetch -- jq -cn '{id: env.ID, title: env.MESSAGE}'
|
|
||||||
intake source env -s echo --set "ID=goodbye"
|
|
||||||
intake source env -s echo --set "MESSAGE=Goodbye, world!"
|
|
||||||
intake channel add -s echo -c home
|
|
||||||
|
|
||||||
touch /home/bob/.intake-setup-done
|
|
||||||
echo "done"
|
|
106
demo/default.nix
106
demo/default.nix
@ -1,106 +0,0 @@
|
|||||||
{ pkgs, lib, ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
system.stateVersion = "25.05";
|
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; [
|
|
||||||
jq
|
|
||||||
];
|
|
||||||
|
|
||||||
# Set up two users to demonstrate the user separation
|
|
||||||
users.users.alice = {
|
|
||||||
isNormalUser = true;
|
|
||||||
password = "a";
|
|
||||||
uid = 1000;
|
|
||||||
};
|
|
||||||
|
|
||||||
users.users.bob = {
|
|
||||||
isNormalUser = true;
|
|
||||||
password = "b";
|
|
||||||
uid = 1001;
|
|
||||||
};
|
|
||||||
|
|
||||||
# Set up intake for both users
|
|
||||||
services.intake.extraPackages = with pkgs; [
|
|
||||||
jq
|
|
||||||
];
|
|
||||||
services.intake.users = {
|
|
||||||
alice = {
|
|
||||||
enable = true;
|
|
||||||
listen.addr = "0.0.0.0";
|
|
||||||
listen.port = 6001;
|
|
||||||
};
|
|
||||||
bob = {
|
|
||||||
enable = true;
|
|
||||||
listen.addr = "0.0.0.0";
|
|
||||||
listen.port = 6002;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# Forward both ports
|
|
||||||
virtualisation.forwardPorts = [
|
|
||||||
{
|
|
||||||
from = "host";
|
|
||||||
host.port = 6001;
|
|
||||||
guest.port = 6001;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
from = "host";
|
|
||||||
host.port = 6002;
|
|
||||||
guest.port = 6002;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
# Disable nixos-shell autologin
|
|
||||||
services.getty.autologinUser = lib.mkForce null;
|
|
||||||
|
|
||||||
# Disable default mounts
|
|
||||||
nixos-shell.mounts = {
|
|
||||||
mountHome = false;
|
|
||||||
mountNixProfile = false;
|
|
||||||
cache = "none";
|
|
||||||
};
|
|
||||||
|
|
||||||
# Define a setup service to create some demo content
|
|
||||||
systemd.services =
|
|
||||||
let
|
|
||||||
setupFor = userName: script: {
|
|
||||||
description = "Intake demo setup for ${userName}";
|
|
||||||
serviceConfig = {
|
|
||||||
User = userName;
|
|
||||||
Type = "oneshot";
|
|
||||||
RemainAfterExit = true;
|
|
||||||
};
|
|
||||||
path = [ pkgs.intake ];
|
|
||||||
environment.INTAKE_DATA_DIR = "/home/${userName}/.local/share/intake";
|
|
||||||
wantedBy = [ "intake-${userName}.service" ];
|
|
||||||
before = [ "intake-${userName}.service" ];
|
|
||||||
after = [ "network.target" ];
|
|
||||||
script = builtins.readFile ./${userName}.sh;
|
|
||||||
};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
intake-alice-setup = setupFor "alice";
|
|
||||||
intake-bob-setup = setupFor "bob";
|
|
||||||
};
|
|
||||||
|
|
||||||
# Include some demo instructions
|
|
||||||
environment.etc.issue.text = ''
|
|
||||||
###
|
|
||||||
# Welcome to the intake demo! Log in as `alice` with password `a` to begin.
|
|
||||||
#
|
|
||||||
# Exit the VM with ctrl+a x, or switch to the qemu console with ctrl+a c and `quit`.
|
|
||||||
###
|
|
||||||
|
|
||||||
'';
|
|
||||||
|
|
||||||
users.motd = ''
|
|
||||||
|
|
||||||
###
|
|
||||||
# The web interfaces are exposed at http://localhost:6001 and http://localhost:6002
|
|
||||||
#
|
|
||||||
# Within this demo VM, you can run `intake` CLI commands.
|
|
||||||
###
|
|
||||||
|
|
||||||
'';
|
|
||||||
}
|
|
34
flake.lock
generated
34
flake.lock
generated
@ -1,22 +1,20 @@
|
|||||||
{
|
{
|
||||||
"nodes": {
|
"nodes": {
|
||||||
"nixos-shell": {
|
"flake-parts": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": [
|
"nixpkgs-lib": "nixpkgs-lib"
|
||||||
"nixpkgs"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1732727306,
|
"lastModified": 1736143030,
|
||||||
"narHash": "sha256-4R+OVEmJ8yR7/gsxMQtC39b9f61SvELYQwKeXGAyFfo=",
|
"narHash": "sha256-+hu54pAoLDEZT9pjHlqL9DNzWz0NbUn8NEAHP7PQPzU=",
|
||||||
"owner": "Mic92",
|
"owner": "hercules-ci",
|
||||||
"repo": "nixos-shell",
|
"repo": "flake-parts",
|
||||||
"rev": "c61dce7cf5dc263d237ba8a7fc175b09642f96eb",
|
"rev": "b905f6fc23a9051a6e1b741e1438dbfc0634c6de",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "Mic92",
|
"owner": "hercules-ci",
|
||||||
"repo": "nixos-shell",
|
"repo": "flake-parts",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -36,9 +34,21 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"nixpkgs-lib": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1735774519,
|
||||||
|
"narHash": "sha256-CewEm1o2eVAnoqb6Ml+Qi9Gg/EfNAxbRx1lANGVyoLI=",
|
||||||
|
"type": "tarball",
|
||||||
|
"url": "https://github.com/NixOS/nixpkgs/archive/e9b51731911566bbf7e4895475a87fe06961de0b.tar.gz"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"type": "tarball",
|
||||||
|
"url": "https://github.com/NixOS/nixpkgs/archive/e9b51731911566bbf7e4895475a87fe06961de0b.tar.gz"
|
||||||
|
}
|
||||||
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixos-shell": "nixos-shell",
|
"flake-parts": "flake-parts",
|
||||||
"nixpkgs": "nixpkgs"
|
"nixpkgs": "nixpkgs"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
85
flake.nix
85
flake.nix
@ -2,64 +2,45 @@
|
|||||||
description = "Universal and extensible feed aggregator";
|
description = "Universal and extensible feed aggregator";
|
||||||
|
|
||||||
inputs = {
|
inputs = {
|
||||||
|
flake-parts.url = "github:hercules-ci/flake-parts";
|
||||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
nixos-shell.url = "github:Mic92/nixos-shell";
|
|
||||||
nixos-shell.inputs.nixpkgs.follows = "nixpkgs";
|
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs =
|
outputs =
|
||||||
{
|
inputs@{ flake-parts, ... }:
|
||||||
self,
|
flake-parts.lib.mkFlake { inherit inputs; } {
|
||||||
nixpkgs,
|
systems = [
|
||||||
nixos-shell,
|
"x86_64-linux"
|
||||||
}:
|
"aarch64-linux"
|
||||||
let
|
"aarch64-darwin"
|
||||||
inherit (nixpkgs.lib) nixosSystem;
|
"x86_64-darwin"
|
||||||
system = "x86_64-linux";
|
];
|
||||||
pkgs = nixpkgs.legacyPackages.${system};
|
perSystem =
|
||||||
in
|
|
||||||
{
|
|
||||||
formatter = nixpkgs.legacyPackages.${system}.nixfmt-rfc-style;
|
|
||||||
|
|
||||||
packages.${system} =
|
|
||||||
let
|
|
||||||
pkgs = (
|
|
||||||
import nixpkgs {
|
|
||||||
inherit system;
|
|
||||||
overlays = [ self.overlays.default ];
|
|
||||||
}
|
|
||||||
);
|
|
||||||
in
|
|
||||||
{
|
{
|
||||||
default = self.packages.${system}.intake;
|
pkgs,
|
||||||
inherit (pkgs) intake;
|
self',
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
formatter = pkgs.nixfmt-rfc-style;
|
||||||
|
|
||||||
|
packages = {
|
||||||
|
intake = pkgs.callPackage ./package.nix { };
|
||||||
|
default = self'.packages.intake;
|
||||||
|
};
|
||||||
|
|
||||||
|
devShells.default = pkgs.mkShell {
|
||||||
|
packages = [
|
||||||
|
pkgs.go
|
||||||
|
pkgs.gopls
|
||||||
|
pkgs.go-tools
|
||||||
|
pkgs.gotools
|
||||||
|
pkgs.cobra-cli
|
||||||
|
pkgs.air
|
||||||
|
];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
flake = {
|
||||||
devShells.${system}.default = pkgs.mkShell {
|
|
||||||
packages = [
|
|
||||||
pkgs.go
|
|
||||||
pkgs.gopls
|
|
||||||
pkgs.go-tools
|
|
||||||
pkgs.gotools
|
|
||||||
pkgs.cobra-cli
|
|
||||||
pkgs.air
|
|
||||||
pkgs.nixos-shell
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
overlays.default = final: prev: {
|
|
||||||
intake = final.callPackage ./package.nix { };
|
|
||||||
};
|
|
||||||
|
|
||||||
nixosModules.default = import ./module.nix self;
|
|
||||||
|
|
||||||
nixosConfigurations."demo" = nixosSystem {
|
|
||||||
inherit system;
|
|
||||||
modules = [
|
|
||||||
nixos-shell.nixosModules.nixos-shell
|
|
||||||
self.nixosModules.default
|
|
||||||
./demo
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
130
module.nix
130
module.nix
@ -1,130 +0,0 @@
|
|||||||
flake:
|
|
||||||
{
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
pkgs,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
|
|
||||||
let
|
|
||||||
inherit (lib)
|
|
||||||
filterAttrs
|
|
||||||
foldl
|
|
||||||
imap1
|
|
||||||
mapAttrsToList
|
|
||||||
mkEnableOption
|
|
||||||
mkIf
|
|
||||||
mkMerge
|
|
||||||
mkOption
|
|
||||||
mkPackageOption
|
|
||||||
types
|
|
||||||
;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options = {
|
|
||||||
services.intake = {
|
|
||||||
package = mkPackageOption pkgs "intake" { };
|
|
||||||
|
|
||||||
extraPackages = mkOption {
|
|
||||||
type = types.listOf types.package;
|
|
||||||
default = [ ];
|
|
||||||
description = "Extra packages available to all enabled users and their intake services.";
|
|
||||||
};
|
|
||||||
|
|
||||||
users = mkOption {
|
|
||||||
description = "User intake service definitions.";
|
|
||||||
default = { };
|
|
||||||
type = types.attrsOf (
|
|
||||||
types.submodule {
|
|
||||||
options = {
|
|
||||||
enable = mkEnableOption "intake, a universal and extensible feed aggregator.";
|
|
||||||
|
|
||||||
dataDir = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = "/home/$USER/.local/share/intake";
|
|
||||||
description = "The data directory for this user's intake service.";
|
|
||||||
};
|
|
||||||
|
|
||||||
listen.addr = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
default = "127.0.0.1";
|
|
||||||
description = "The listen address for this user's intake service.";
|
|
||||||
};
|
|
||||||
|
|
||||||
listen.port = mkOption {
|
|
||||||
type = types.port;
|
|
||||||
default = 80;
|
|
||||||
description = "The listen port for this user's intake service.";
|
|
||||||
};
|
|
||||||
|
|
||||||
extraPackages = mkOption {
|
|
||||||
type = types.listOf types.package;
|
|
||||||
default = [ ];
|
|
||||||
description = "Extra packages available to this user and their intake service.";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config =
|
|
||||||
let
|
|
||||||
intakeCfg = config.services.intake;
|
|
||||||
enabledUsers = filterAttrs (userName: userCfg: userCfg.enable) intakeCfg.users;
|
|
||||||
enabledUserNames = mapAttrsToList (userName: userCfg: userName) enabledUsers;
|
|
||||||
userPackages = userName: [ intakeCfg.package ] ++ intakeCfg.extraPackages ++ intakeCfg.users.${userName}.extraPackages;
|
|
||||||
crontabWrapper = pkgs.writeShellScriptBin "crontab" ''
|
|
||||||
exec ${config.security.wrapperDir}/crontab "$@"
|
|
||||||
'';
|
|
||||||
in
|
|
||||||
{
|
|
||||||
# Apply the overlay so intake is included in pkgs.
|
|
||||||
nixpkgs.overlays = [ flake.overlays.default ];
|
|
||||||
|
|
||||||
# Give every intake user the shared packages and their user-specific packages.
|
|
||||||
users.users =
|
|
||||||
let
|
|
||||||
addPackagesToUser = userName: {
|
|
||||||
${userName}.packages = userPackages userName;
|
|
||||||
};
|
|
||||||
in
|
|
||||||
mkMerge (map addPackagesToUser enabledUserNames);
|
|
||||||
|
|
||||||
# Enable cron
|
|
||||||
services.cron.enable = true;
|
|
||||||
|
|
||||||
# Define a user service for each configured user
|
|
||||||
systemd.services =
|
|
||||||
let
|
|
||||||
runScript =
|
|
||||||
userName:
|
|
||||||
pkgs.writeShellScript "intake-run.sh" ''
|
|
||||||
mkdir -p $INTAKE_DATA_DIR
|
|
||||||
# Add the setuid wrapper directory so `crontab` is accessible
|
|
||||||
export PATH="${config.security.wrapperDir}:$PATH"
|
|
||||||
${intakeCfg.package}/bin/intake serve --addr ${enabledUsers.${userName}.listen.addr} --port ${toString enabledUsers.${userName}.listen.port}
|
|
||||||
'';
|
|
||||||
# systemd service definition for a single user, given `services.intake.users.userName` = `userCfg`
|
|
||||||
userServiceConfig = userName: userCfg: {
|
|
||||||
"intake-${userName}" = {
|
|
||||||
description = "Intake service for user ${userName}";
|
|
||||||
script = "${runScript userName}";
|
|
||||||
path = [ crontabWrapper ] ++ intakeCfg.extraPackages ++ userCfg.extraPackages;
|
|
||||||
environment = {
|
|
||||||
INTAKE_DATA_DIR = "/home/${userName}/.local/share/intake";
|
|
||||||
};
|
|
||||||
serviceConfig = {
|
|
||||||
User = userName;
|
|
||||||
Type = "simple";
|
|
||||||
};
|
|
||||||
wantedBy = [ "multi-user.target" ];
|
|
||||||
after = [ "network.target" ];
|
|
||||||
enable = userCfg.enable;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
in
|
|
||||||
mkMerge (mapAttrsToList userServiceConfig enabledUsers);
|
|
||||||
};
|
|
||||||
}
|
|
@ -128,17 +128,6 @@ func (env *Env) editSource(writer http.ResponseWriter, req *http.Request) {
|
|||||||
http.Error(writer, err.Error(), 500)
|
http.Error(writer, err.Error(), 500)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if envName == "INTAKE_CRON" {
|
|
||||||
specs, err := core.GetCronSources(env.db)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("error: failed to get cron specs: %v", err)
|
|
||||||
} else {
|
|
||||||
err = core.UpdateCrontab(env.db, specs)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("error: failed to update crontab: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
actionName := req.PostForm.Get("actionName")
|
actionName := req.PostForm.Get("actionName")
|
||||||
|
Loading…
Reference in New Issue
Block a user