| .ssh | ||
| crates | ||
| docker | ||
| nix | ||
| scripts | ||
| .dockerignore | ||
| .envrc | ||
| .gitignore | ||
| .nts-srv.toml | ||
| .sops.yaml | ||
| Cargo.lock | ||
| Cargo.toml | ||
| compose.yaml | ||
| Dockerfile | ||
| flake.lock | ||
| flake.nix | ||
| README.md | ||
nts
nts is a single user git provider over ssh.
It has build in single-threaded "CI" and
therefore mainly focused on notes-syncing.
Client side
There is a client side cli (nts),
aimed at providing wrapper commands to manage git
repositories on a remote git host.
The main commands are mainly client side (create, remove, clone),
while others rely on the server-side binary nts-srv (list and search).
Server side
The server-side binary enhances the client-side functionality.
It additionally provides the option to run a "CI",
which builds the git repositories (on change) via nix build
and uploads the results to a ResultStore.
Security
nts tries to be as simple and light-weight as possible.
Therefore it relys a lot on other technologies that I consider "already installed"
(that play nice with my setup).
nts works mainly by executing commands directly on the server,
saving git repositories directly on the server and building directly on the server without a lot
of sandboxing (aka none).
You should therefore be carefull where to put your ssh keys (as usually)
and take care of sandboxing by creating a seperate user for nts.
Usage (client side)
nts provides the basic utilities to manage git repositories on a remote server:
- create
- delete
- move
- list / search
- clone
Create a repository
nts add PATH
nts new PATH
This will create a git repository on the remote host (by default under $HOST/data),
however the data direcotry can be changed by the server-side environment variable: NTS_SRV_DATA.
The path can be as nested as one wants.
Under the hood this just calls
git init --barevia ssh.
The path is always relative to the data directory and can start with ~/, ./, / or directly with the path
(all mean the same thing).
Additionally one can pass the --clone flag, which will tell nts to directly clone the repository after creating it.
Delete a repository
nts rm PATH
nts remove PATH
This will delte a git repository on the remote host.
The path specification is the same as in nts add.
Under the hood this just calls
rm PATHvia ssh.
Move a repository
nts mv SRC DEST
nts move SRC DEST
This will move a repository from one place to another.
Unter the hood this just calls
mv SRC DESTvia ssh. So it should behaive excatly likemv
List / Search repositories
This command relies on
nts-srvpresent.
nts ls
nts list
Will list all git repositories currently present inside the data directory on the host.
nts query SEARCH
nts search SEARCH
Will filter the repository list to only the repositories matching the given SEARCH query. Currently the search string is fuzzy-matched, but this might change in the future to provide a better search experience.
Clone a repository
nts clone REMOTE [LOCAL]
This is essentially just a wrapper around git clone
that allows to use the same PATH notation as in every other command.
It additionally also handles the host configuration the same as every other command and therefore makes cloning a bit easier.
Configuration
nts needs a bit of configuration to work correctly,
mainly it needs to know which remote host to use.
The configuration file can be edited via:
nts config OPTION VALUE
The config file will be placed in one of the following direcotires (which ever is defined first):
$NTS_CONFIG$LOCALAPPDATA/nts$XDG_CONFIG_HOME/nts$HOME/.config/nts
the config file is named
config.json.
The following options are supported:
Hostname
via cli:
nts config host HOSTNAME
via config.json:
{
"host": "HOSTNAME"
}
Specifies which ssh hostname to connect to.
The host has to be setup with a ssh-key that needs no more authentication,
as nts calls ssh internally.
Ssh config
via cli:
nts config ssh PATH
via config.json:
{
"ssh_config": "PATH"
}
Overwrites the default ssh config file (~/.ssh/config) that will be used.
CI runner
The CI runner is a server-side feature that needs nts-srv installed and correctly setup (see docker documentation).
When activated, nts-srv will listen on changed inside the data directory and try to build git repositories on change with nix.
For this to work the repository has to have a flake.nix which exposes packages.default (that derivation will be build).
Afterwards the contents will be uploaded to the ResultStore. If the derivation is only one file, it will be placed inside a folder,
otherwise the folder structure of the result will be used.
Nextcloud
The nextcloud ResultStore uploads the build artifacts to a nextcloud instance.
The path will be the same as the relative path of the git repository inside the
data directory.
Optionally it will create a share with another user, which allows for an alt-account
to manage the artifact repositories (for improved security).
Installation
nts works best when nts-srv is also installed (on the remote),
but it can be used on its own (to some extend).
nts
The client side executable can be installed via cargo:
cargo install --git https://git.solarpunk.social/krauterbaquette/nts nts
Nix
You can also run nts via nix:
nix run git+https://git.solarpunk.social/krauterbaquette/nts
To include in your system configuration add:
{
inputs = {
nts = {
url = "git+https://git.solarpunk.social/krauterbaquette/nts";
inputs.nixpkgs.follows = "nixpkgs";
};
};
}
nts will be accessable via: inputs.nts.packages.${system}.default
nts-srv
The server side executable can be installed via cargo:
cargo install --git https://git.solarpunk.social/krauterbaquette/nts nts-srv
But has to be sym-linked to ~/.local/bin/nts-srv, because nts will
only search there for it.
Default location of the installed binary is:
$HOME/.cargo, see here
After installing nts-srv you can start the "CI" with nts-srv watch.
Nix
On NixOS maschines nts-srv can be installed "bare-metal", meaning it will run under a user on said maschine.
You first have to include this repo as an flake-input:
{
inputs = {
nts = {
url = "git+https://git.solarpunk.social/krauterbaquette/nts";
inputs.nixpkgs.follows = "nixpkgs";
};
};
}
You can then import the module:
{ inputs, ... }: {
flake.nixosConfigurations.HOSTNAME = {
imports = [
inputs.nts.nixosModules.nts-srv
];
...
};
}
This will expose a new service:
{
flake.nixosConfigurations.HOSTNAME = {
...
services.nts-srv = { ... };
};
}
With the following options:
| Option | Default | Description |
|---|---|---|
| enable | false |
Wether to setup nts-srv |
| package | self' .packages.server |
The nts-srv package to use |
| user.name | nts |
Username which will run nts-srv and own the repos. A system user with the given username will be created |
| user.home | /var/lib/nts |
Home directory for the user. The repos will be in the data subfolder. |
| user.authorizedKeyFile | [ ] |
List of ssh public key files for said user |
| user.authorizedKeys | [ ] |
List of ssh public keys for said user |
| config.noCI | false |
This will disable the "CI" (not run nts-srv watch) |
| config.file | { } |
Here you can specify the contents of the nts-srv config file as nix values (that get transformed to toml) |
The environment will be setup by the
nts-srv-initsystemd service, which will afterwards start thents-srv-ciservice, given thatconfig.noCI = false.You can see the logs for the CI service with
journalctl -u nts-srv-ciorsystemctl status nts-srv-ci.
Docker
On any other distro that NixOS it is recommended to use the docker image provided at dock.woisek.de/tofubar/nts-srv.
This is currently not publicly available and I am stil searching for an option to publish my docker builds (other than docker hub).
In the mean time you can compile the docker image yourself.
You can use docker-compose with a setup like this:
services:
nts-srv:
container_name: nts-srv
restart: unless-stopped
image: dock.woisek.de/tofubar/nts-srv:latest
ports:
# allow ssh connections to port 22
- "127.0.0.1:3030:22"
environment:
# start nts-srv watch
NTS_SRV_CI: "true"
volumes:
# set ssh public key
- type: bind
source: .ssh/id_local_ed25519.pub
target: /home/nts/.ssh/authorized_keys
# set nts config -> important for CI config
- type: bind
source: .nts-srv/docker.toml
target: /home/nts/.config/nts-srv/config.toml
# create data volume for easier backups
- ./data.docker:/home/nts/data
The supportet tags are named after the nts-srv version (e.g. version 1.2.2 has the tag name 1.2.2).
There is also the latest tag which points to the currently latest version.
Bare metal
A bare metal setup is not recommended (other than with NixOS).
If you still want to check out nix/module.nix and try to translate that to "normal linux".
Configuration (nts)
nts can be configured via the cli with nts config. See:
nts config --help
The configuration is saved inside a config.json file, in one of these direcotries:
$NTS_CONFIG$XDG_CONFIG_HOME/nts$HOME/.config/nts
They will be searched in this order and the first one that is found will be used.
The config.json file can contain the following values:
{
version: 1, // [constant]
host: String, // ssh host to connect to e.g. notes
ssh_config: Option<String> // path to ssh config to use [default: ~/.ssh/config]
}
versionspecifies the config file version for better migration later on.
The host must be set and have an identitation file configured, so nts can connect to the host without user interaction.
Configuration (nts-srv)
nts-srv can be configured (in theory) via the cli with nts-srv config. see:
nts-srv config --help
However most of the time you want to create the config.toml before hand.
It must be placed inside one of the following direcotries:
$NTS_SRV_CONFIG$XDG_CONFIG_HOME/nts-srv$HOME/.config/nts-srv
The config.toml file can contain the following values:
version = 1 # [constant]
build = Option<String> # base directory for CI builds (they will be placed inside "$build/result") [default: $HOME]
skip_nix_gc = Option<bool> # if true `nts watch` wont start a garbage collect thread [default: false]
nix_exe = Option<String> # path to nix executable [default: nix]
[nextcloud] # use nextcloud as a ResultStore for `nts watch` [optional]
url = String # base url of the nextcloud instance (http://example.nextcloud.com)
user = String # username to use for the upload
share_to = Option<String> # when set, the uploaded folder will be shared (readonly) with the given username
# eiter password or password_file must be set
password = Eiter<String> # password for the user account
password_file = Eiter<String> # file containing the user password. The fill will be trimmed at the start & end
Keep in mind, that this way your password can be read in clear text. For now this is the best solution i could come up with, but you should make sure that the config file / password file can only be ready by your user.
Why toml and json?
The nts configuration file was created way before the need for an nts-srv config file.
At this time i basically only knew json config file.
By the time nts-srv got its config file I discovered the beauty and simplicity of toml config files
so nts-srv got one.
nts stil has the json file because of backwards compatability (which is the best joke i've ever told),
but most likly this will change in the future when I become interested in creating a migration system.
I am the only user btw
Development
It is recommended the use the
nixpackage manager while developing.
There are three devShells available:
default- contains rust tools for developmentnts- setup a local dev config for nts which can connect to a local docker containernts-srv- setup a local dev config for nts-srv. This way you can runnts-srvon the local maschine or run the docker container
Docker container
Run:
docker compose up --build
to start a local nts-srv container on 127.0.0.1:3030.
When inside the nts devShell you can then
rm .ssh/known_hosts # remove old public key
ssh local -F .ssh/config echo hello # save the new public key
cargo r --bin nts -- list # use nts with the local docker container
When not using nix you can see inside the
nix/dev.nixon how to recreate the envrionment.
This project uses sops to save credentials for a test nextcloud account. You might setup your own there / ask for access.
Publish
To create a new version you can run nix run .#version, if you have write access to the docker registry.
See nix run .#version -- --help for usage information.