Skip to content

Commit 579c994

Browse files
committed
initial release
1 parent 182bee9 commit 579c994

File tree

20 files changed

+243
-1
lines changed

20 files changed

+243
-1
lines changed

.github/FUNDING.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
open_collective: linuxserver

.github/workflows/BuildImage.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
name: Build Image
2+
3+
on: [push, pull_request, workflow_dispatch]
4+
5+
env:
6+
ENDPOINT: "aptalca/tape"
7+
8+
jobs:
9+
build:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/[email protected]
13+
14+
- name: Build image
15+
run: |
16+
docker build --no-cache -t ${{ github.sha }} .
17+
- name: Tag image
18+
if: ${{ github.ref == format('refs/heads/main') }}
19+
run: |
20+
docker tag ${{ github.sha }} ghcr.io/${ENDPOINT}:${{ github.sha }}
21+
docker tag ${{ github.sha }} ghcr.io/${ENDPOINT}:latest
22+
docker tag ${{ github.sha }} ${ENDPOINT}:${{ github.sha }}
23+
docker tag ${{ github.sha }} ${ENDPOINT}:latest
24+
- name: Login to GitHub Container Registry
25+
if: ${{ github.ref == format('refs/heads/main') }}
26+
run: |
27+
echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u aptalca --password-stdin
28+
- name: Push tags to GitHub Container Registry
29+
if: ${{ github.ref == format('refs/heads/main') }}
30+
run: |
31+
docker push ghcr.io/${ENDPOINT}:${{ github.sha }}
32+
docker push ghcr.io/${ENDPOINT}:latest
33+
- name: Login to DockerHub
34+
if: ${{ github.ref == format('refs/heads/main') }}
35+
run: |
36+
echo ${{ secrets.DOCKERPASS }} | docker login -u aptalca --password-stdin
37+
- name: Push tags to DockerHub
38+
if: ${{ github.ref == format('refs/heads/main') }}
39+
run: |
40+
docker push ${ENDPOINT}:${{ github.sha }}
41+
docker push ${ENDPOINT}:latest

.github/workflows/baseupdate.yml

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
name: Base Updater
2+
3+
on:
4+
schedule:
5+
- cron: '17 */6 * * *'
6+
workflow_dispatch:
7+
8+
env:
9+
REPO: "tape"
10+
11+
jobs:
12+
base-updater:
13+
runs-on: ubuntu-latest
14+
steps:
15+
- name: Check out repo
16+
uses: actions/[email protected]
17+
18+
- name: Check for updates and trigger
19+
run: |
20+
DISTRO=$(cat Dockerfile | grep 'FROM' | sed 's|.*baseimage-\(.*\):.*|\1|')
21+
TAG=$(cat Dockerfile | grep 'FROM' | sed 's|.*:\(.*\)|\1|')
22+
token=$(curl -sX GET \
23+
"https://ghcr.io/token?scope=repository%3Alinuxserver%2Fbaseimage-${DISTRO}%3Apull" \
24+
| jq -r '.token')
25+
EXTDIGEST=$(curl -I \
26+
--header "Accept: application/vnd.docker.distribution.manifest.v2+json" \
27+
--header "Accept: application/vnd.oci.image.index.v1+json" \
28+
--header "Authorization: Bearer ${token}" \
29+
"https://ghcr.io/v2/linuxserver/baseimage-${DISTRO}/manifests/${TAG}" \
30+
| grep 'docker-content-digest' | awk '{print $2}')
31+
if [ -z "${EXTDIGEST}" ]; then
32+
echo "Unable to retrieve external digest. Exiting."
33+
exit 0
34+
else
35+
echo "External digest retrieved: ${EXTDIGEST}"
36+
fi
37+
LASTDIGEST=$(cat baseimage-digest.txt)
38+
if [ "${LASTDIGEST}" != "${EXTDIGEST}" ]; then
39+
echo "Last used baseimage digest: ${LASTDIGEST}"
40+
echo "Baseimage seems to have been updated. Updating baseimage digest and triggering a build."
41+
curl -iX POST \
42+
-H "Authorization: token ${{ secrets.CR_PAT }}" \
43+
-H "Accept: application/vnd.github.v3+json" \
44+
-d "{\"ref\":\"refs/heads/main\"}" \
45+
https://api.github.com/repos/aptalca/${REPO}/actions/workflows/BuildImage.yml/dispatches
46+
echo -n "${EXTDIGEST}" > baseimage-digest.txt
47+
git config --local user.email "[email protected]"
48+
git config --local user.name "AptalcaBot"
49+
git add . || :
50+
git commit -m '[bot] Updating baseimage digest' || :
51+
git push || :
52+
else
53+
echo "Baseimage seems to be the same. Skipping."
54+
fi

.github/workflows/permissions.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
name: Permission check
2+
on:
3+
pull_request:
4+
paths:
5+
- '**/run'
6+
- '**/finish'
7+
- '**/check'
8+
jobs:
9+
permission_check:
10+
uses: linuxserver/github-workflows/.github/workflows/init-svc-executable-permissions.yml@v1

Dockerfile

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
FROM ghcr.io/linuxserver/baseimage-alpine:3.21
2+
3+
LABEL maintainer="aptalca"
4+
5+
RUN \
6+
echo "**** install runtime packages ****" && \
7+
apk add --no-cache --upgrade \
8+
logrotate \
9+
mt-st \
10+
tar && \
11+
echo "**** fix logrotate ****" && \
12+
sed -i "s#/var/log/messages {}.*# #g" /etc/logrotate.conf && \
13+
sed -i 's,/usr/sbin/logrotate /etc/logrotate.conf,/usr/sbin/logrotate /etc/logrotate.conf -s /config/logrotate.status,g' \
14+
/etc/periodic/daily/logrotate && \
15+
rm -rf \
16+
/tmp/*
17+
18+
# add local files
19+
COPY /root /

README.md

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,45 @@
1-
# tape
1+
# Docker container for managing tape (lto) drives
2+
3+
Includes `mt-st` package which provides the `mt` command for interfacing with tape drives, as well as gnu `tar`.
4+
5+
Also includes cron for scheduling tape backups and restores. Crontab is included in the `/config` folder and changes require a container restart.
6+
7+
## Requirements:
8+
9+
- Needs the tape devices mounted (ie. `--device /dev/st0 --device /dev/nst0`)
10+
- Needs a bind mount for the `/config` folder
11+
- Add optional bind mounts for the paths you'd like to copy from and to
12+
13+
## Usage:
14+
15+
Basic facts about tapes and how they are operated with `mt` and `tar`:
16+
17+
- Tape drives are for sequential reading and writing. Each tar file is written and appended with an `EOF` marker that defines the end of the file.
18+
- Tape drives can easily and relatively quickly identify the EOF files to determine the beginning and end of each file.
19+
- Writing and reading operations always begin on where the drive head currently is. Pay close attention to that prior to each operation.
20+
- `/dev/st0` is rewinding device. After each operation, the tape is rewound to the beginning. `/dev/nst0` is non-rewinding and the head remains at its location at the end of each operation.
21+
- `mt -f /dev/nst0 status` will show the status of the drive head. If it's at a file (vs a block), it will list the `File number`. If it's at the beginning of a file, it will list `EOF` at the bottom (except for the first file, which is really called `File number=0`, which will show `BOT` indicating the `beginning of tape`).
22+
- You can seek to the beginning via `mt -f /dev/nst0 rewind` or `mt -f /dev/nst0 asf 0`
23+
- You can seek to the beginning of any file via `mt -f /dev/nst0 asf X`with `X` being the file number (starting from `0`)
24+
25+
### Writing to tape:
26+
27+
- For the first write, make sure to rewind via `mt -f /dev/nst0 rewind` and confirm with `status`.
28+
- With tar, you can write directly to the tape via `tar -cvf /dev/nst0 sourcedirectory1 sourcedirectory2`.
29+
- If you used the non-rewinding `nst0` device, the drive head should be at the beginning of the second file, indicated by `File number=1` and `EOF` in `status` output.
30+
- To write the second file, make sure the `status` shows `File number=1` and `EOF`.
31+
- Same command, `tar -cvf /dev/nst0 sourcedirectory1 sourcedirectory2`, will now write the second tar file and the head should move to `File number=1`.
32+
- If you overwrite the first file, all subsequent files will be lost. Pay attention to where the head is before each write operation. You can use `mt` to forward to the end of the tape to be sure.
33+
34+
### Reading from tape:
35+
36+
- You can seek to the beginning of files with the command `mt -f /dev/nst0 asf X` with X being the file number (starting with 0).
37+
- To copy the first file from tape to the current folder on the local machine, rewind via `mt -f /dev/nst0 rewind` (or via `mt -f /dev/nst0 asf 0`).
38+
- Use the tar command to extract from tape: `tar -xvf /dev/nst0`. It will read the first file all the way to the EOF, and extract it to the local disk.
39+
- To copy the second file from tape, seek to it via `mt -f /dev/nst0 asf 1` and extract via `tar -xvf /dev/nst0`.
40+
41+
There are plenty more `mt` commands and arguments listed on its manpage: https://linux.die.net/man/1/mt
42+
43+
## Important Notice:
44+
45+
Never do `mt -f /dev/nst0 erase` unless you know it's really what you want. The manpage is not clear about it, but it actually does a `secure erase`, it takes a really long time (8+ hrs) and you can't cancel it once started. Killing or force killing the process doesn't work, `docker stop` and `docker kill` fail. The only way is to cut the power to the drive, which could damage the drive head.

root/defaults/tape.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
echo "***********************************"
2+
echo "* *"
3+
echo "* *"
4+
echo "***********************************"
5+
echo $(date)
6+
echo "Enter your tape copy/sync lines here"

root/etc/crontabs/root

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# do daily/weekly/monthly maintenance
2+
# min hour day month weekday command
3+
*/15 * * * * run-parts /etc/periodic/15min
4+
0 * * * * run-parts /etc/periodic/hourly
5+
0 2 * * * run-parts /etc/periodic/daily
6+
0 3 * * 6 run-parts /etc/periodic/weekly
7+
0 5 1 * * run-parts /etc/periodic/monthly
8+
# tape
9+
#0 2 * * 3 /config/tape.sh >> /config/logs/log.txt 2>&1 && chown abc:abc /config/logs/log.txt

root/etc/logrotate.d/logrotate

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/config/logs/*.txt {
2+
weekly
3+
rotate 52
4+
compress
5+
delaycompress
6+
nodateext
7+
missingok
8+
notifempty
9+
sharedscripts
10+
su abc abc
11+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
2+
───────────────────────────────────────
3+
Brought to you by . . .
4+
5+
_______ __ __ _______ ________
6+
| \| \ | \ \| \
7+
| ▓▓▓▓▓▓▓\ ▓▓ | ▓▓ ▓▓▓▓▓▓▓\ ▓▓▓▓▓▓▓▓
8+
| ▓▓ | ▓▓ ▓▓ | ▓▓ ▓▓ | ▓▓ ▓▓__
9+
| ▓▓ | ▓▓ ▓▓ | ▓▓ ▓▓ | ▓▓ ▓▓ \
10+
| ▓▓ | ▓▓ ▓▓ | ▓▓ ▓▓ | ▓▓ ▓▓▓▓▓
11+
| ▓▓__/ ▓▓ ▓▓__/ ▓▓ ▓▓__/ ▓▓ ▓▓_____
12+
| ▓▓ ▓▓\▓▓ ▓▓ ▓▓ ▓▓ ▓▓ \
13+
\▓▓▓▓▓▓▓ \▓▓▓▓▓▓ \▓▓▓▓▓▓▓ \▓▓▓▓▓▓▓▓
14+
15+
16+
Based on images from linuxserver.io
17+
───────────────────────────────────────

0 commit comments

Comments
 (0)