{
"path": "/3mjdorjdcd22s",
"site": "at://did:plc:nuc33thnsiqzhytkleyr5jek/site.standard.publication/3mjdo3xyaoc2l",
"tags": [
"restic",
"backup",
"dotfiles",
"self-hosting"
],
"$type": "site.standard.document",
"title": "Setting up Restic with rest-server",
"content": {
"$type": "pub.leaflet.content",
"pages": [
{
"id": "019d845d-3ad2-7bb5-9413-9ddb6f4f6cb0",
"$type": "pub.leaflet.pages.linearDocument",
"blocks": [
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.header",
"level": 2,
"plaintext": "Context"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"plaintext": "I recently decided to start using my own home server to store my dotfiles. The main reasons are simplicity, privacy, and security. I previously stored them in a repository on my GitHub account and installed them with Ansible, but I have increasingly found it cumbersome when trying to keep them updated and in sync. On GitHub, the changes (and mistakes!) I make to my dotfiles are publicly viewable; sometimes I'll make changes several times a day, sometimes scrapping a change entirely when I later realize it was not such a good idea or breaks something in my activity flow. I also would love the convenience of keeping SSH keys and GPG keychains in sync and updated, and storing them on a public server is obviously not an option, nor even in a private repository hosted on GitHub or GitLab."
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.header",
"level": 2,
"plaintext": "Cue Restic"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"plaintext": "My home server is basically just my old 2013 MacBook Pro running Fedora Server edition. It has a 250GB SSD, which is more than enough for what I need. I also have a 1TB external SSD which I will use to emulate redundancy. I installed and configure the rest-server software to act as a backend for my Restic backups."
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.header",
"level": 2,
"plaintext": "Setting up the rest server"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"facets": [
{
"index": {
"byteEnd": 69,
"byteStart": 65
},
"features": [
{
"$type": "pub.leaflet.richtext.facet#code"
}
]
},
{
"index": {
"byteEnd": 199,
"byteStart": 186
},
"features": [
{
"uri": "https://github.com/restic/rest-server/releases",
"$type": "pub.leaflet.richtext.facet#link"
}
]
}
],
"plaintext": "First build the rest-server binary and move it to a directory in PATH. This step requires Go 1.11 or higher. Optionally, you can download the latest compiled rest-server binary from its releases page."
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.code",
"language": "shellscript",
"plaintext": "git clone https://github.com/restic/rest-server \ncd rest-server/ \nCGO_ENABLED=0 go build -o rest-server ./cmd/rest-server \nsudo cp -v rest-server /usr/local/bin/ ",
"syntaxHighlightingTheme": "catppuccin-mocha"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"plaintext": "I also configured the systemd unit file so that rest-server runs on startup with the appropriate flags. I need only configure the options User, Group, ExecStart, and ReadWritePaths in the [Service] section:"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.code",
"language": "systemd",
"plaintext": "[Service] \nType=simple \nUser=restic-data \nGroup=restic-data \nExecStart=/usr/local/bin/rest-server --path /opt/restic-backups --no-auth \nRestart=always \nRestartSec=5 \n \n# Optional security enhancements \n\nNoNewPrivileges=yes \nPrivateTmp=yes \nProtectSystem=strict \nProtectHome=yes \nReadWritePaths=/opt/restic-backups ",
"syntaxHighlightingTheme": "catppuccin-mocha"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"facets": [
{
"index": {
"byteEnd": 55,
"byteStart": 46
},
"features": [
{
"$type": "pub.leaflet.richtext.facet#code"
}
]
}
],
"plaintext": "Since this is a local home server, I pass the --no-auth flag to the rest-server ExecStart command."
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"plaintext": "I now create the restic-data user and group."
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.unorderedList",
"children": [
{
"$type": "pub.leaflet.blocks.unorderedList#listItem",
"content": {
"$type": "pub.leaflet.blocks.text",
"facets": [
{
"index": {
"byteEnd": 58,
"byteStart": 53
},
"features": [
{
"$type": "pub.leaflet.richtext.facet#code"
}
]
},
{
"index": {
"byteEnd": 76,
"byteStart": 74
},
"features": [
{
"$type": "pub.leaflet.richtext.facet#code"
}
]
}
],
"plaintext": "Ensure a default home directory is not created under /home by passing the -M flag."
}
},
{
"$type": "pub.leaflet.blocks.unorderedList#listItem",
"content": {
"$type": "pub.leaflet.blocks.text",
"facets": [
{
"index": {
"byteEnd": 63,
"byteStart": 44
},
"features": [
{
"$type": "pub.leaflet.richtext.facet#code"
}
]
},
{
"index": {
"byteEnd": 75,
"byteStart": 73
},
"features": [
{
"$type": "pub.leaflet.richtext.facet#code"
}
]
}
],
"plaintext": "Set a custom home directory for the user at /opt/restic-backups with the -d flag."
}
},
{
"$type": "pub.leaflet.blocks.unorderedList#listItem",
"content": {
"$type": "pub.leaflet.blocks.text",
"facets": [
{
"index": {
"byteEnd": 45,
"byteStart": 32
},
"features": [
{
"$type": "pub.leaflet.richtext.facet#code"
}
]
}
],
"plaintext": "Ensure the shell is assigned to /sbin/nologin."
}
},
{
"$type": "pub.leaflet.blocks.unorderedList#listItem",
"content": {
"$type": "pub.leaflet.blocks.text",
"facets": [
{
"index": {
"byteEnd": 84,
"byteStart": 76
},
"features": [
{
"$type": "pub.leaflet.richtext.facet#code"
}
]
}
],
"plaintext": "The restic-data user is not meant to be used for logging in, so we pass the --system flag."
}
}
]
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.code",
"language": "shellscript",
"plaintext": "sudo useradd -c \"Restic Data\" -M -d /opt/restic-backups -s /sbin/nologin --system restic-data ",
"syntaxHighlightingTheme": "catppuccin-mocha"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.unorderedList",
"children": [
{
"$type": "pub.leaflet.blocks.unorderedList#listItem",
"content": {
"$type": "pub.leaflet.blocks.text",
"plaintext": "Ensure the backups path exists and has appropriate permissions."
}
},
{
"$type": "pub.leaflet.blocks.unorderedList#listItem",
"content": {
"$type": "pub.leaflet.blocks.text",
"plaintext": "Copy the systemd unit file to a location where systemd will look for it."
}
},
{
"$type": "pub.leaflet.blocks.unorderedList#listItem",
"content": {
"$type": "pub.leaflet.blocks.text",
"plaintext": "Enable and start the rest-server systemd service."
}
}
]
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.code",
"language": "shellscript",
"plaintext": "sudo mkdir /opt/restic-backups \nsudo chown -R restic-data:restic-data /opt/restic-backups \nsudo cp -v rest-server.service /etc/systemd/system/ \nsudo systemctl daemon-reload \nsudo systemctl enable --now rest-server.service ",
"syntaxHighlightingTheme": "catppuccin-mocha"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"plaintext": "Since I'm using a firewall, I ensure the port the rest-server listens on is allowed locally:"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.code",
"language": "shellscript",
"plaintext": "sudo firewall-cmd --zone`FedoraServer --permanent --add-port`8000/tcp \nsudo firewall-cmd --reload ",
"syntaxHighlightingTheme": "catppuccin-mocha"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"plaintext": "Now on the host, which in this case is my laptop, I have the Restic client installed from my distribution's package repository."
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.unorderedList",
"children": [
{
"$type": "pub.leaflet.blocks.unorderedList#listItem",
"content": {
"$type": "pub.leaflet.blocks.text",
"plaintext": "Initialize a Restic storage repository on the server from the host, and supply it with a password. This password will be used every time I attempt to access the storage repository."
}
},
{
"$type": "pub.leaflet.blocks.unorderedList#listItem",
"content": {
"$type": "pub.leaflet.blocks.text",
"plaintext": "Backup my dotfiles"
}
}
]
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.code",
"language": "shellscript",
"plaintext": "restic -r rest:http://local-server:8000/dotfiles init\nrestic -r rest:http://local-server:8000/dotfiles backup ~/dotfiles",
"syntaxHighlightingTheme": "catppuccin-mocha"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"plaintext": "One of the best features of Restic is that it makes restory backups really simple. It also provides snapshot functionality, so I can restore different versions of specific files from other snapshots."
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.code",
"language": "shellscript",
"plaintext": "restic -r rest:http://local-server:8000/dotfiles snapshots \n \nenter password for repository: \nrepository 9a280eb7 opened successfully, password is correct \nID Time Host Tags Paths \n------------------------------------------------------------------------------ \n\n11738fec 2021-04-12 09:13:17 toolbox /var/home/jeff/dotfiles \ndfc99aa3 2021-04-12 10:31:39 toolbox /var/home/jeff/dotfiles \nf951eedf 2021-04-12 11:25:21 toolbox /var/home/jeff/dotfiles \n62371897 2021-04-12 18:43:53 toolbox /var/home/jeff/dotfiles \n------------------------------------------------------------------------------ \n\n4 snapshots ",
"syntaxHighlightingTheme": "catppuccin-mocha"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"facets": [
{
"index": {
"byteEnd": 64,
"byteStart": 63
},
"features": [
{
"$type": "pub.leaflet.richtext.facet#code"
}
]
}
],
"plaintext": "Since Restic saves the backup's absolute path, restoring it to / will ensure it is restored to its original location on the local filesystem. To restore a snapshot:"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.code",
"language": "shellscript",
"plaintext": "restic -r rest:http://local-server:8000/dotfiles restore dfc99aa3 --target / ",
"syntaxHighlightingTheme": "catppuccin-mocha"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"plaintext": "To list files in a snapshot:"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.code",
"language": "shellscript",
"plaintext": "restic -r rest:http://local-server:8000/dotfiles ls dfc99aa3 ",
"syntaxHighlightingTheme": "catppuccin-mocha"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.text",
"plaintext": "Yay, very nice!"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.header",
"level": 2,
"plaintext": "Resources"
}
},
{
"$type": "pub.leaflet.pages.linearDocument#block",
"block": {
"$type": "pub.leaflet.blocks.unorderedList",
"children": [
{
"$type": "pub.leaflet.blocks.unorderedList#listItem",
"content": {
"$type": "pub.leaflet.blocks.text",
"facets": [
{
"index": {
"byteEnd": 19,
"byteStart": 0
},
"features": [
{
"uri": "https://restic.net/",
"$type": "pub.leaflet.richtext.facet#link"
}
]
}
],
"plaintext": "https://restic.net/"
}
},
{
"$type": "pub.leaflet.blocks.unorderedList#listItem",
"content": {
"$type": "pub.leaflet.blocks.text",
"facets": [
{
"index": {
"byteEnd": 37,
"byteStart": 0
},
"features": [
{
"uri": "https://github.com/restic/rest-server",
"$type": "pub.leaflet.richtext.facet#link"
}
]
}
],
"plaintext": "https://github.com/restic/rest-server"
}
}
]
}
}
]
}
]
},
"description": "",
"publishedAt": "2021-04-14T01:12:00.000Z"
}