Compare commits
	
		
			3 Commits
		
	
	
		
			6066188ef1
			...
			ad4de2994a
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| ad4de2994a | |||
| 6876a63250 | |||
| d1d561cb70 | 
							
								
								
									
										8
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								Makefile
									
									
									
									
									
								
							@@ -31,6 +31,14 @@ test-setup:
 | 
				
			|||||||
	#git ls-files -z | tar --null -T - -cf - | tar -C /tmp/test-borg -xvf -
 | 
						#git ls-files -z | tar --null -T - -cf - | tar -C /tmp/test-borg -xvf -
 | 
				
			||||||
	/tmp/test-borg/initial-setup.sh
 | 
						/tmp/test-borg/initial-setup.sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Pull master and rebase "setup-$HOSTNAME" branch onto it
 | 
				
			||||||
 | 
					.PHONY: rebase
 | 
				
			||||||
 | 
					rebase:
 | 
				
			||||||
 | 
						git checkout master
 | 
				
			||||||
 | 
						git pull
 | 
				
			||||||
 | 
						git checkout -
 | 
				
			||||||
 | 
						git rebase master
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.PHONY: clean
 | 
					.PHONY: clean
 | 
				
			||||||
clean:
 | 
					clean:
 | 
				
			||||||
	rm -f README.html
 | 
						rm -f README.html
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -89,7 +89,7 @@ Design
 | 
				
			|||||||
  - `/opt/borg/ssh/id_ecdsa`
 | 
					  - `/opt/borg/ssh/id_ecdsa`
 | 
				
			||||||
    - configured on server for read-write operation
 | 
					    - configured on server for read-write operation
 | 
				
			||||||
    - used for manual recovery, management, pruning
 | 
					    - used for manual recovery, management, pruning
 | 
				
			||||||
    - password in bitwarden (under `borg [hostname]`, user `read-write ssh key`)
 | 
					    - password in bitwarden (under `borg <hostname>`, user `read-write ssh key`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Pruning requires the password and is a manual operation, and should only
 | 
					- Pruning requires the password and is a manual operation, and should only
 | 
				
			||||||
  be run when the client has not been compromised.
 | 
					  be run when the client has not been compromised.
 | 
				
			||||||
@@ -104,7 +104,7 @@ Design
 | 
				
			|||||||
- Backup script `/opt/borg/backup.py` uses configuration in
 | 
					- Backup script `/opt/borg/backup.py` uses configuration in
 | 
				
			||||||
  `/opt/borg/config.yaml` to generate our own list of files, excluding
 | 
					  `/opt/borg/config.yaml` to generate our own list of files, excluding
 | 
				
			||||||
  anything that's too large by default.  This requires borg 1.2.0b1
 | 
					  anything that's too large by default.  This requires borg 1.2.0b1
 | 
				
			||||||
  or newer, which is why the setup scripts download a specific version.
 | 
					  or newer.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										29
									
								
								backup.py
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								backup.py
									
									
									
									
									
								
							@@ -241,10 +241,8 @@ def main(argv: list[str]):
 | 
				
			|||||||
    base = pathlib.Path(__file__).parent
 | 
					    base = pathlib.Path(__file__).parent
 | 
				
			||||||
    parser.add_argument('-c', '--config',
 | 
					    parser.add_argument('-c', '--config',
 | 
				
			||||||
                        help="Config file", default=str(base / "config.yaml"))
 | 
					                        help="Config file", default=str(base / "config.yaml"))
 | 
				
			||||||
    parser.add_argument('-b', '--borg',
 | 
					    parser.add_argument('-v', '--vars',
 | 
				
			||||||
                        help="Borg command", default=str(base / "borg.sh"))
 | 
					                        help="Variables file", default=str(base / "vars.sh"))
 | 
				
			||||||
    parser.add_argument('-N', '--notify',
 | 
					 | 
				
			||||||
                        help="Notify command", default=str(base / "notify.sh"))
 | 
					 | 
				
			||||||
    parser.add_argument('-n', '--dry-run', action="store_true",
 | 
					    parser.add_argument('-n', '--dry-run', action="store_true",
 | 
				
			||||||
                        help="Just print log output, don't run borg")
 | 
					                        help="Just print log output, don't run borg")
 | 
				
			||||||
    parser.add_argument('-d', '--debug', action="store_true",
 | 
					    parser.add_argument('-d', '--debug', action="store_true",
 | 
				
			||||||
@@ -253,6 +251,27 @@ def main(argv: list[str]):
 | 
				
			|||||||
    args = parser.parse_args()
 | 
					    args = parser.parse_args()
 | 
				
			||||||
    config = Config(args.config)
 | 
					    config = Config(args.config)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Parse variables from vars.sh
 | 
				
			||||||
 | 
					    hostname = os.uname().nodename
 | 
				
			||||||
 | 
					    borg = str(base / "borg.sh")
 | 
				
			||||||
 | 
					    notify = str(base / "notify.sh")
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        with open(args.vars) as f:
 | 
				
			||||||
 | 
					            for line in f:
 | 
				
			||||||
 | 
					                m = re.match(r"\s*export\s*([A-Z_]+)=(.*)", line)
 | 
				
			||||||
 | 
					                if not m:
 | 
				
			||||||
 | 
					                    continue
 | 
				
			||||||
 | 
					                var = m.group(1)
 | 
				
			||||||
 | 
					                value = m.group(2)
 | 
				
			||||||
 | 
					                if var == "HOSTNAME":
 | 
				
			||||||
 | 
					                    hostname = value
 | 
				
			||||||
 | 
					                if var == "BORG":
 | 
				
			||||||
 | 
					                    borg = value
 | 
				
			||||||
 | 
					                if var == "BORG_DIR":
 | 
				
			||||||
 | 
					                    notify = pathlib.Path(value) / "notify.sh"
 | 
				
			||||||
 | 
					    except Exception as e:
 | 
				
			||||||
 | 
					        self.log('W', f"failed to parse variables from {args.vars}: {str(e)}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Run backup
 | 
					    # Run backup
 | 
				
			||||||
    backup = Backup(config, args.dry_run)
 | 
					    backup = Backup(config, args.dry_run)
 | 
				
			||||||
    captured_output: list[bytes] = []
 | 
					    captured_output: list[bytes] = []
 | 
				
			||||||
@@ -275,7 +294,7 @@ def main(argv: list[str]):
 | 
				
			|||||||
                                 "--compression", "zstd,3",
 | 
					                                 "--compression", "zstd,3",
 | 
				
			||||||
                                 "--paths-from-stdin",
 | 
					                                 "--paths-from-stdin",
 | 
				
			||||||
                                 "--paths-delimiter", "\\0",
 | 
					                                 "--paths-delimiter", "\\0",
 | 
				
			||||||
                                 "::{hostname}-{now:%Y%m%d-%H%M%S}"],
 | 
					                                 "::" + hostname + "-{now:%Y%m%d-%H%M%S}"],
 | 
				
			||||||
                                stdin=subprocess.PIPE,
 | 
					                                stdin=subprocess.PIPE,
 | 
				
			||||||
                                stdout=subprocess.PIPE,
 | 
					                                stdout=subprocess.PIPE,
 | 
				
			||||||
                                stderr=subprocess.STDOUT)
 | 
					                                stderr=subprocess.STDOUT)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +1,10 @@
 | 
				
			|||||||
#!/bin/bash
 | 
					#!/bin/bash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# These can be overridden when running this script
 | 
					# These can be overridden when running this script
 | 
				
			||||||
 | 
					HOSTNAME=${HOSTNAME:-$(hostname)}
 | 
				
			||||||
BACKUP_HOST=${BACKUP_HOST:-backup.jim.sh}
 | 
					BACKUP_HOST=${BACKUP_HOST:-backup.jim.sh}
 | 
				
			||||||
BACKUP_USER=${BACKUP_USER:-jim-backups}
 | 
					BACKUP_USER=${BACKUP_USER:-jim-backups}
 | 
				
			||||||
BACKUP_REPO=${BACKUP_REPO:-borg/$(hostname)}
 | 
					BACKUP_REPO=${BACKUP_REPO:-borg/${HOSTNAME}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Main dir is where this repo was checked out
 | 
					# Main dir is where this repo was checked out
 | 
				
			||||||
BORG_DIR="$(realpath "$(dirname "$0")")"
 | 
					BORG_DIR="$(realpath "$(dirname "$0")")"
 | 
				
			||||||
@@ -14,7 +15,7 @@ cd "${BORG_DIR}"
 | 
				
			|||||||
BORG_BIN="${BORG_DIR}/Borg.bin"
 | 
					BORG_BIN="${BORG_DIR}/Borg.bin"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Use stable host ID in case MAC address changes
 | 
					# Use stable host ID in case MAC address changes
 | 
				
			||||||
HOSTID="$(hostname -f)@$(python -c 'import uuid;print(uuid.getnode())')"
 | 
					HOSTID="${HOSTNAME}@$(python -c 'import uuid;print(uuid.getnode())')"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function error_handler() {
 | 
					function error_handler() {
 | 
				
			||||||
    echo "Error at $1 line $2:"
 | 
					    echo "Error at $1 line $2:"
 | 
				
			||||||
@@ -86,7 +87,7 @@ create_borg_vars()
 | 
				
			|||||||
export BACKUP_USER=${BACKUP_USER}
 | 
					export BACKUP_USER=${BACKUP_USER}
 | 
				
			||||||
export BACKUP_HOST=${BACKUP_HOST}
 | 
					export BACKUP_HOST=${BACKUP_HOST}
 | 
				
			||||||
export BACKUP_REPO=${BACKUP_REPO}
 | 
					export BACKUP_REPO=${BACKUP_REPO}
 | 
				
			||||||
export HOSTNAME=$(hostname)
 | 
					export HOSTNAME=${HOSTNAME}
 | 
				
			||||||
export BORG_REPO=${BORG_REPO}
 | 
					export BORG_REPO=${BORG_REPO}
 | 
				
			||||||
export BORG_HOST_ID=${HOSTID}
 | 
					export BORG_HOST_ID=${HOSTID}
 | 
				
			||||||
export BORG_PASSCOMMAND="cat ${BORG_DIR}/passphrase"
 | 
					export BORG_PASSCOMMAND="cat ${BORG_DIR}/passphrase"
 | 
				
			||||||
@@ -273,7 +274,7 @@ EOF
 | 
				
			|||||||
update_paths()
 | 
					update_paths()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    sed -i \
 | 
					    sed -i \
 | 
				
			||||||
        -e "s!\${HOSTNAME}!$(hostname)!g" \
 | 
					        -e "s!\${HOSTNAME}!${HOSTNAME}!g" \
 | 
				
			||||||
        -e "s!\${BORG_DIR}!${BORG_DIR}!g" \
 | 
					        -e "s!\${BORG_DIR}!${BORG_DIR}!g" \
 | 
				
			||||||
        -e "s!\${BACKUP_USER}!${BACKUP_USER}!g" \
 | 
					        -e "s!\${BACKUP_USER}!${BACKUP_USER}!g" \
 | 
				
			||||||
        -e "s!\${BACKUP_HOST}!${BACKUP_HOST}!g" \
 | 
					        -e "s!\${BACKUP_HOST}!${BACKUP_HOST}!g" \
 | 
				
			||||||
@@ -287,14 +288,14 @@ update_paths()
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
git_setup()
 | 
					git_setup()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if ! git checkout -b "setup-$(hostname)" ; then
 | 
					    if ! git checkout -b "setup-${HOSTNAME}" ; then
 | 
				
			||||||
        warn "Git setup failed; ignoring"
 | 
					        warn "Git setup failed; ignoring"
 | 
				
			||||||
        return
 | 
					        return
 | 
				
			||||||
    fi
 | 
					    fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    log "Committing local changes to git"
 | 
					    log "Committing local changes to git"
 | 
				
			||||||
    git add README.md borg-backup.service borg-backup.timer vars.sh
 | 
					    git add README.md borg-backup.service borg-backup.timer vars.sh
 | 
				
			||||||
    git commit -a -m "autocommit after initial setup on $(hostname)"
 | 
					    git commit -a -m "autocommit after initial setup on ${HOSTNAME}"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
log "Configuration:"
 | 
					log "Configuration:"
 | 
				
			||||||
@@ -315,11 +316,11 @@ git_setup
 | 
				
			|||||||
echo
 | 
					echo
 | 
				
			||||||
notice "Add these two passwords to Bitwarden:"
 | 
					notice "Add these two passwords to Bitwarden:"
 | 
				
			||||||
notice ""
 | 
					notice ""
 | 
				
			||||||
notice "      Name: borg $(hostname)"
 | 
					notice "      Name: borg ${HOSTNAME}"
 | 
				
			||||||
notice "  Username: read-write ssh key"
 | 
					notice "  Username: read-write ssh key"
 | 
				
			||||||
notice "  Password: $PASS_SSH"
 | 
					notice "  Password: $PASS_SSH"
 | 
				
			||||||
notice ""
 | 
					notice ""
 | 
				
			||||||
notice "      Name: borg $(hostname)"
 | 
					notice "      Name: borg ${HOSTNAME}"
 | 
				
			||||||
notice "  Username: repo key"
 | 
					notice "  Username: repo key"
 | 
				
			||||||
notice "  Password: $PASS_REPOKEY"
 | 
					notice "  Password: $PASS_REPOKEY"
 | 
				
			||||||
notice ""
 | 
					notice ""
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user