A VPS is a server you run yourself, so its backups are your job too. This guide sets up automatic, off-site backups from a Linux VPS to Amazon S3: a locked-down bucket, a backup user that can only write to one folder, nightly database dumps and file archives, and a restore you have actually tested. Every command says where it runs.
Create the S3 bucket and a least-privilege IAM user from the AWS Console or your own laptop, never from the VPS. Turn on versioning and a lifecycle rule. On the VPS, install AWS CLI v2 with a profile for that user, then schedule a script that streams a database dump and a tar archive of /etc and your web root into the bucket. Test a restore every month. For encrypted, deduplicated backups, restic to the same bucket is the stronger option.
1. Before you start
- This is for your own VPS. Domain India VPS plans are self-managed with root access. Don't assume a provider-side copy of your server exists or covers your data; ask support what applies to your plan, and keep your own off-site backups regardless.
- Shared hosting is different. Our cPanel and DirectAdmin plans include weekly JetBackup backups you restore from the panel; see backing up and restoring with JetBackup. You can't install the AWS CLI system-wide there.
- You need an AWS account, SSH access to the VPS as root or a
sudouser, and about 30 minutes.
Where each command runs:
| Label | Where | Why |
|---|---|---|
| Admin side | AWS Console in your browser, or AWS CLI on your laptop with admin credentials | Creating buckets and users needs powerful rights that should never sit on a server |
| VPS | Your server, over SSH | It only uploads and reads its own backups |
2. Plan what to back up
- Databases, as dumps. Copying live database files is not a backup.
- Web roots and app data, for example
/var/wwwor/home. - Configuration:
/etc, and anything else you changed by hand. - Leave out caches,
node_modules, build output and logs you don't need.
Choose a region close to the server: Asia Pacific (Mumbai) ap-south-1 or (Hyderabad) ap-south-2 for servers in India. Decide how long to keep copies, for example 30 daily copies plus older versions for 90 days.
3. Create and secure the bucket (admin side)
- Create the bucket.In the S3 console choose Create bucket, give it a globally unique name such as
acme-vps-backups, and pick your region. Leave Block all public access on. - Keep the defaults for security.New buckets already encrypt every object (SSE-S3) and have ACLs disabled.
- Turn on Versioningunder Properties › Bucket Versioning. A deleted or overwritten backup then remains as an older version.
- Add a lifecycle ruleunder Management: expire noncurrent versions after 90 days and delete incomplete multipart uploads after 7 days.
The same bucket from the AWS CLI on your laptop:
# Admin side, not the VPS
aws s3api create-bucket --bucket acme-vps-backups --region ap-south-1 \
--create-bucket-configuration LocationConstraint=ap-south-1
aws s3api put-bucket-versioning --bucket acme-vps-backups \
--versioning-configuration Status=EnabledCheaper storage classes such as Standard-IA and the Glacier classes have minimum storage periods and retrieval charges. Move only old copies there, and check the AWS pricing page before you add transitions.
4. Create a least-privilege backup user (admin side)
In IAM › Users, create a user such as vps-prod01-backup with no console access, attach this policy, and create an access key for it. The user can list and write only under servers/prod01/.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::acme-vps-backups",
"Condition": { "StringLike": { "s3:prefix": ["servers/prod01/*"] } }
},
{
"Effect": "Allow",
"Action": ["s3:PutObject", "s3:GetObject", "s3:DeleteObject", "s3:AbortMultipartUpload"],
"Resource": "arn:aws:s3:::acme-vps-backups/servers/prod01/*"
}
]
}The policy deliberately leaves out s3:DeleteObjectVersion and every bucket-settings permission. With versioning on, anyone who breaks into the VPS can hide the latest files but cannot destroy older versions. For stronger protection against ransomware, look at S3 Object Lock when you create the bucket.
5. Install and configure the AWS CLI (VPS)
# VPS
curl -fsSL "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o awscliv2.zip
unzip -q awscliv2.zip && sudo ./aws/install
aws --version
aws configure --profile backup # access key, secret, region ap-south-1, output json
chmod 600 ~/.aws/credentials ~/.aws/config
aws sts get-caller-identity --profile backup
echo "test $(date -Is)" | aws s3 cp - s3://acme-vps-backups/servers/prod01/test.txt --profile backupOn an ARM server use the aarch64 installer instead. Install unzip first if it is missing (apt install unzip or dnf install unzip).
6. The backup script (VPS)
Store database credentials in /root/.my.cnf (permission 600) so they never appear in the script or the process list. On MariaDB, root on the server can usually log in through the local socket with no password at all.
Save this as /usr/local/bin/s3-backup.sh and run chmod 700 on it:
#!/usr/bin/env bash
set -Eeuo pipefail
export AWS_PROFILE=backup
DEST="s3://acme-vps-backups/servers/prod01"
DAY="$(date +%F)"
# 1. All databases, consistent InnoDB snapshot, streamed and compressed
mysqldump --single-transaction --quick --routines --events --all-databases \
| gzip | aws s3 cp - "$DEST/db/mysql-$DAY.sql.gz" --no-progress
# 2. Configuration and web files as one archive
tar --warning=no-file-changed -czf - /etc /var/www \
--exclude='*/cache/*' --exclude='*/node_modules/*' \
| aws s3 cp - "$DEST/archives/files-$DAY.tar.gz" --no-progress
echo "$(date -Is) backup finished"On newer MariaDB releases the dump tool is also called mariadb-dump; for PostgreSQL use sudo -u postgres pg_dumpall | gzip | aws s3 cp - …. If a single stream may exceed 50 GB, add --expected-size with the approximate byte count so the upload is split into enough parts.
7. Schedule it and watch it (VPS)
Run sudo crontab -e and add:
30 2 * * * /usr/local/bin/s3-backup.sh >> /var/log/s3-backup.log 2>&1A backup that fails silently is worse than none, because you believe you have one. Check the log after the first night, and add an alert: have the script call a health-check URL on success, or mail you the log when it fails. Keep the server clock in sync with chrony or systemd-timesyncd, because AWS rejects requests from a clock that has drifted.
Once a month, restore the latest dump into a test database and extract the archive into a temporary folder. It is the only way to know the files are complete and that you remember the steps when it matters.
8. Restore (VPS)
# List what you have
aws s3 ls s3://acme-vps-backups/servers/prod01/db/ --profile backup
# Restore a database dump
aws s3 cp s3://acme-vps-backups/servers/prod01/db/mysql-2026-09-20.sql.gz - --profile backup \
| gunzip | mysql
# Extract files to a temporary folder first, then copy back what you need
mkdir -p /root/restore
aws s3 cp s3://acme-vps-backups/servers/prod01/archives/files-2026-09-20.tar.gz - --profile backup \
| tar -xz -C /root/restoreTo recover an overwritten or deleted object, open it in the S3 console with Show versions on and download the older version.
9. A stronger option: restic
The simple script above uploads a full copy every night. restic encrypts everything on the server before upload, stores only changed data, and keeps a list of snapshots you can prune by age. It uses the same bucket and backup user:
# VPS
export AWS_PROFILE=backup
export RESTIC_REPOSITORY="s3:s3.ap-south-1.amazonaws.com/acme-vps-backups/servers/prod01/restic"
export RESTIC_PASSWORD_FILE=/root/.restic-pass # a long random password, chmod 600
restic init
restic backup /etc /var/www --exclude='**/cache/**'
restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune
restic restore latest --target /root/restoreStore the restic password somewhere other than the server. Without it, the backups cannot be decrypted by anyone, including you. Pruning uses the s3:DeleteObject permission the backup user already has; with versioning on, pruned data stays as older versions until your lifecycle rule expires it.
10. Troubleshooting
| Error | Likely cause | Fix |
|---|---|---|
| AccessDenied | The policy prefix does not match the path you upload to | Upload under servers/prod01/ or edit the policy |
| SignatureDoesNotMatch or RequestTimeTooSkewed | The server clock is wrong | Enable chrony or systemd-timesyncd |
| mysqldump Access denied | No credentials for the dump | Add them to /root/.my.cnf with permission 600 |
| The job runs by hand but not from cron | cron has a shorter PATH and no profile | Use full paths and set AWS_PROFILE in the script |
| Uploads are slow | Large uncompressed data or busy hours | Exclude caches, schedule at night, or switch to restic |
Frequently asked questions
Does Domain India back up my VPS for me?
Domain India VPS plans are self-managed, so backing up your data is your responsibility. Ask support what applies to your plan, and keep your own off-site backups, such as the S3 setup in this guide, either way.
Should I create the S3 bucket from the VPS?
No. Create the bucket and the IAM user from the AWS Console or your own computer. The VPS should only hold a backup user that can write to its own folder, so a break-in on the server cannot change or delete the bucket.
Which AWS region should I use for a server in India?
Asia Pacific (Mumbai), ap-south-1, or Asia Pacific (Hyderabad), ap-south-2. A nearby region keeps uploads fast.
How do I back up MySQL or MariaDB to S3 without temporary files?
Pipe the dump straight into the AWS CLI: mysqldump --single-transaction --all-databases | gzip | aws s3 cp - s3://bucket/path/file.sql.gz. The --single-transaction option gives a consistent copy of InnoDB tables without locking the site.
How often should I test a restore?
At least once a month, and after any change to the script. Restore the latest dump into a test database and extract the archive into a temporary folder.
Can I use this on Domain India shared hosting?
Not as written: the AWS CLI install and system folders need root. Shared cPanel and DirectAdmin plans include weekly JetBackup backups that you can download and restore from the panel.
Ready to protect your server? Compare VPS plans, read how to access your VPS over SSH, or open a support ticket with any question about your plan. Support is on 24/7 live chat, and tickets get a first response within 15 minutes.
Domain India VPS plans give you full root access to set up backups, software and security your way.
See VPS plans