← Start of tutorial

WIUNIX ACADEMY

MinIO after archival: a private S3 lab from pinned source

Page 3 of 4. Review the earlier steps and prerequisites before continuing.

YOUR SYSTEM. YOUR STEPS.

Where are you working?

Choose your OS and version. The prerequisites, commands and troubleshooting follow your environment.

Ubuntu26.04 LTSReviewed against official documentation ·

USE YOUR OWN VALUES

Configure this tutorial

Set the example values for your environment; related explanations and copy panels update together. Never enter passwords, private keys or tokens. Values stay in this tab and are not sent to the server or share links. Check actual DNS, certificates and network policy before running commands.

Different IP addresses, domains or ports? Open the settings below, change the values and select “Apply to tutorial”, then copy the updated commands.

Set values for my environment6 editable values
09

LET’S BUILD

Provision once, then enable versioning before writes

Run once against the new empty lab. The helper creates two private buckets, one new user and a narrowly scoped named policy. Versioning is enabled by root on academy-objects before writing data. Private default access is not an anonymous public bucket policy.

bash

Inside the disposable container · terminal

set -eu
cd '/srv/academy-minio/minio-7aac2a2c5b7c882e68c1ce017d8256be2feea27f'
GOTOOLCHAIN=local CGO_ENABLED=0 GOMAXPROCS=2 GOPATH='/srv/academy-minio/gopath'   '/srv/academy-minio/go/bin/go' build -p 2 -trimpath   -o '/srv/academy-minio/bin/provision' '/srv/academy-minio/provision.go'
'/srv/academy-minio/bin/provision'
'/srv/academy-minio/bin/mc' --config-dir '/srv/academy-minio/root-client' version enable 'lab/academy-objects'
'/srv/academy-minio/bin/mc' --config-dir '/srv/academy-minio/root-client' version info 'lab/academy-objects'
How do I know it worked?

New scoped identity created; version info says enabled for academy-objects.

10

LET’S BUILD

Prove writes, versions and denied operations

Upload two synthetic contents to probe. Read the current object and inspect historical entries as root. A scoped application must fail to list academy-objects-outside and fail to delete its own object. The expected errors are part of the test. Do not add delete/admin grants simply to make every command succeed.

bash

Inside the disposable container · terminal

set -eu
cd '/srv/academy-minio'
printf 'academy version one
' > run/object.txt
bin/mc --config-dir app-client cp run/object.txt 'lab/academy-objects/probe'
printf 'academy version two
' > run/object.txt
bin/mc --config-dir app-client cp run/object.txt 'lab/academy-objects/probe'
bin/mc --config-dir app-client cat 'lab/academy-objects/probe'
bin/mc --config-dir root-client ls --versions 'lab/academy-objects/probe'
if bin/mc --config-dir app-client ls 'lab/academy-objects-outside'; then exit 1; fi
if bin/mc --config-dir app-client rm 'lab/academy-objects/probe'; then exit 1; fi
printf '%s
' 'Expected: version two, two versions, outside listing and deletion denied'
How do I know it worked?

Current content is version two; two versions exist; outside listing and object deletion are denied.

11

LET’S BUILD

Retrieve the older version without replacing the current object

As the separate recovery authority, root lists exactly two versions, selects the first version ID and reads its bytes into a new exclusive private file. It must contain version one. This proves historical-object retrieval, not a complete restore of every version or automatic undelete. Do not overwrite the current object to inspect history.

bash

Inside the disposable container · terminal

set -eu
python3 - <<'PY'
import subprocess,json,hashlib,os
from pathlib import Path
r=Path('/srv/academy-minio')
base=[str(r/'bin/mc'),'--config-dir',str(r/'root-client')]
target='lab/academy-objects/probe'
p=subprocess.run(base+['ls','--json','--versions',target],capture_output=True,text=True,check=True)
rows=[json.loads(line) for line in p.stdout.splitlines() if line]
versions=[x for x in rows if x.get('key')=='probe' and x.get('versionId')]
assert len(versions)==2, 'Expect exactly two versions in this new lab'
old=min(versions,key=lambda x:x['versionOrdinal'])['versionId']
p=subprocess.run(base+['cat','--version-id',old,target],capture_output=True,check=True)
assert p.stdout==b'academy version one\n', 'Historical bytes differ'
path=r/'backup'/'historical-probe'
fd=os.open(path,os.O_WRONLY|os.O_CREAT|os.O_EXCL|os.O_NOFOLLOW,0o600)
with os.fdopen(fd,'wb') as f:f.write(p.stdout)
print('Historical version retrieved separately; SHA256',hashlib.sha256(p.stdout).hexdigest())
PY
How do I know it worked?

Version one is recovered to a new0600 file; version two remains current.

12

LET’S BUILD

Export one current object and verify its reimport

Export the current probe to an unused local backup filename, reimport under a new object key, download to a separate unused restore filename and compare bytes. Refuse existing targets. This is a tested current-object round trip inside one lab, not an off-host disaster-recovery backup or restoration of all versions/IAM/metadata.

bash

Inside the disposable container · terminal

set -eu
cd '/srv/academy-minio'
# Current-object export, not a complete version/IAM/retention backup.
test ! -e 'backup/probe'
test ! -L 'backup/probe'
test ! -e 'restored/probe'
test ! -L 'restored/probe'
bin/mc --config-dir root-client cp 'lab/academy-objects/probe' 'backup/probe'
bin/mc --config-dir root-client cp 'backup/probe' 'lab/academy-objects/restored-probe'
bin/mc --config-dir app-client cp 'lab/academy-objects/restored-probe' 'restored/probe'
cmp 'backup/probe' 'restored/probe'
sha256sum 'backup/probe' 'restored/probe'
How do I know it worked?

cmp succeeds and both SHA256 values match; original object remains present.

Versioning, retention and parity solve different failures

Versioning retains previous versions; it does not prevent a privileged user from deleting them. An ordinary delete can create a delete marker, while deleting a particular version can remove data permanently. Our application deliberately lacks delete and GetObjectVersion permissions. Root historical access is a separate recovery authority.

Object Lock, governance/compliance retention, legal holds and lifecycle deletion require an explicit regulatory/data-retention design and client tests. They are not enabled or accepted by this recipe. Do not assume a bucket can be converted safely after ingestion or bypass retention as an ordinary recovery action.

One process and one container filesystem are neither erasure-coded HA nor a backup. A real design must cover failure domains, free capacity, healing, storage monitoring, KMS/key recovery where used, object metadata/version history and protected IAM/configuration export. Replication can also propagate mistakes; rehearse independent off-site recovery with measured RPO/RTO.

Keep S3 signatures intact across a future proxy

No reverse proxy is installed in this lab. In a later supported deployment, give S3 API and console distinct intended endpoints and restrict console management independently. Preserve the signed HTTP Host, including a nondefault port, and the signed path/query. Path rewriting under a prefix, Host replacement, URL decoding/re-encoding or arbitrary scheme redirects can invalidate SigV4. The hostname used to sign must be reachable by the actual client.

A presigned URL is a bearer capability until expiry; do not log/share it as harmless metadata. TLS must validate the real endpoint SAN and chain, and clocks must agree. Configure proxy upload/body/time limits and streaming behavior against actual SDK multipart/range workloads. Test application-specific S3 compatibility; an S3 label does not guarantee every AWS operation, retention mode or console feature.

Never fix signature failures by disabling TLS verification, making the bucket public or moving the client to the console port. Record the actual Host/path/query chain and client endpoint without exposing Authorization headers, presigned query strings or keys. The source-level review establishes these design boundaries; no public proxy/ACME/browser-console login acceptance is claimed.

Explore all tutorials ↗