Files
gaussian-wellworks/Infrastructure/Implementation Runbook.md
2026-04-30 15:13:50 -05:00

1276 lines
24 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Runbook: Self-hosted Pilot
## Gaussian Wellworks
## 1. Runbook Objective
This runbook provides a step-by-step procedure to deploy a secure, self-hosted pilot environment in DigitalOcean within five business days, including infrastructure provisioning, domain and DNS configuration, email platform integration, containerized Nextcloud deployment, and secure HTTPS access via reverse proxy. The objective is to deliver a fully functional, production-ready pilot system that supports internal collaboration and client file ingestion workflows, with validated end-to-end functionality (upload, access, delivery), clear administrative controls, and a scalable foundation for future expansion or migration.
## 2. Critical Dependencies
### 2.1 Business Domain Ownership
### 2.2 Administrative Access
### 2.3 Decision Checklist
## 3. Detailed Implementation Runbook
### 3.1 Create Digital Ocean Account
**Objective**
Provision a cloud account capable of hosting the pilot environment:
- Account created and secured
- Billing configured
- Team/ownership clarified
- Ready to provision Droplet (Task 3.3)
**Architectural Context**
This account will own:
- Droplet (server)
- Backups/snapshots
- Networking (firewall, IP)
- Future scaling resources
**Step 1 - Register Account**
Go to:
```
https://cloud.digitalocean.com/registrations/new
```
1.1 Enter account details
```
Email address (prefer client-owned)
Password (strong, unique)
```
1.2 Verify email
```
Check inbox
Click verification link
```
**Step 2 - Secure the Account (Highly Recommended)**
2.1 Enable Two-Factor Authentication (2FA)
Navigate to:
```
Settings → Security → Two-Factor Authentication
```
Enable using:
Authenticator app (recommended)
2.2 Store recovery codes
✔ Save securely (password manager)
**Step 3 - Add Billing Method**
Navigate to:
```
Billing → Payment Methods
```
3.1 Add payment method
3.2 Confirm billing active
**Step 4 - Create/Confirm Team Context**
DigitalOcean uses teams/projects.
Navigate:
```
Projects → Default Project
```
4.1 Rename project (recommended)
GaussianWellworks-Pilot
4.2 Assign resources later
Droplets will be attached here.
**Step 5 - Configure Default Settings**
5.1 Enable backups (account-level awareness)
While backups are enabled per droplet, confirm understanding:
✔ Backups cost ~20% of droplet price
✔ Enable during droplet creation
5.2 (Optional) Enable monitoring
Settings → Monitoring → Enable
*Not required for pilot, but useful later.*
**Validation Checklist**
- [✔] Account created
- [✔] Email verified
- [✔] 2FA enabled
- [✔] Billing method added
- [✔] Project created/renamed
- [✔] Dashboard accessible
- [✔] Able to initiate droplet creation
### 3.2 Create SSH Key Pair (Windows 11)
**Objective**
Create an SSH key pair on a Windows 11 workstation and upload the public key to DigitalOcean so it can be attached when provisioning the Ubuntu droplet.
DigitalOcean recommends SSH keys over passwords for Droplet access, and uploaded team keys can be selected during Droplet creation.
**Generate key**
```Powershell
</> Powershell
ssh-keygen -t ed25519 -C "admin@company.com"
```
Accept default path:
```
C:\Users\<user>\.ssh\id_ed25519
```
**Copy public key**
```Powershell
</> Powershell
Get-Content $env:USERPROFILE\.ssh\id_ed25519.pub | Set-Clipboard
```
**Upload to DigitalOcean**
- Settings → Security → SSH Keys → Add
- Name: admin-windows11
**Validation Checklist**
- [✔] Key visible in DigitalOcean
### 3.3 Provision Droplet
**Objective**
Provision a production-ready virtual server (Droplet) in DigitalOcean that will host:
- Nextcloud (Docker-based)
- Reverse proxy (Nginx)
- Supporting services
This step establishes the core infrastructure node for the entire pilot.
**Create Dropet**
1. Login to DigitalOcean
2. Click Create
3. Select Droplets
**Droplet Configuration**
```
Image: Ubuntu 22.04 LTS
Plan: Premium Intel
Size: 2 vCPU / 8GB RAM
Region: closest to users
Auth: SSH key
Backups: Enabled
Hostname: gw-drive-01
```
**Test SSH**
```Powershell
ssh root@<IP>
```
**Validation Checklist**
- [✔] SSH login works
- [✔] IP recorded
### 3.4 Initial Server Configuration
**Objective**
Harden the freshly provisioned Ubuntu server and establish a secure administrative baseline before any application deployment.
At the end of this task, the system will:
- Allow SSH access only via key-based authentication
- Use a non-root administrative user
- Be fully patched and up to date
- Be ready for firewall and application installation
**Create admin user**
```Bash
</> Bash
adduser adminuser
usermod -aG sudo adminuser
```
**Copy SSH key**
```Bash
</> Bash
rsync --archive --chown=adminuser:adminuser ~/.ssh /home/adminuser
```
**Disable root login**
```Bash
</> Bash
sudo tee /etc/ssh/sshd_config > /dev/null << 'EOF'
PermitRootLogin no
PasswordAuthentication no
EOF
```
```Bash
</> Bash
sudo systemctl restart ssh
```
**Test login**
```Powershell
</> Powershell
ssh adminuser@<IP>
```
**Update system**
```Bash
</> Bash
sudo apt update
sudo apt upgrade -y
sudo apt autoremove -y
```
**Validation**
[✔] adminuser login works
[✔] root login blocked
[✔] system updated
### 3.5 Configure Firewall
**Objective**
Establish a baseline network security posture so that:
- Only required ports are exposed
- All other inbound traffic is blocked
- SSH access remains available
- The system is prepared for web access (Nextcloud + HTTPS)
**DigitalOcean Firewall**
Allow:
```
22 (SSH) → your IP
80 (HTTP) → all
443 (HTTPS) → all
```
Attach to droplet.
**UFW**
```Bash
</> Bash
sudo apt install ufw -y
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
```
**Validation**
```Bash
</> Bash
sudo ufw status
```
### 3.6 Configure DNS
**Objective**
Create a public DNS record so that:
```
drive.company.com → your Droplet public IP
```
This enables:
- Browser access to Nextcloud (Day 3)
- SSL certificate issuance (Lets Encrypt)
- A stable, user-friendly endpoint
**Create A record**
```
Host: drive
Value: <DROPLET_IP>
TTL: 300
```
**Validate**
```Powershell
</> Powershell
nslookup drive.company.com
```
*Note*
⚠ DNS propagation required before SSL
### 3.7 Install Docker
**Objective**
Prepare the server to run containerized services by installing:
- Docker Engine (container runtime)
- Docker Compose (multi-container orchestration)
**Required Dependencies**
```Bash
</> Bash
sudo apt install ca-certificates curl gnupg -y
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
```
```Bash
</> Bash
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
```
**Install Docker**
```Bash
</> Bash
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin -y
```
**Enable Docker**
```Bash
</> Bash
sudo systemctl enable docker
sudo systemctl start docker
sudo usermod -aG docker adminuser
```
Reconnect SSH.
**Test**
```Bash
</> Bash
docker run hello-world
```
### 3.10 Deploy Nextcloud
**Objective**
Deploy a production-capable Nextcloud stack using Docker Compose, including:
- Nextcloud application container
- MariaDB database container
- Redis (for performance + file locking)
- Persistent storage volumes
**Create directory**
```Bash
</> Bash
mkdir -p ~/apps/nextcloud
cd ~/apps/nextcloud
```
**Create .env**
```Bash
</> Bash
sudo tee .env > /dev/null << 'EOF'
MYSQL_ROOT_PASSWORD=StrongRootPassword
MYSQL_PASSWORD=StrongDBPassword
MYSQL_DATABASE=nextcloud
MYSQL_USER=nextcloud
NEXTCLOUD_ADMIN_USER=admin
NEXTCLOUD_ADMIN_PASSWORD=StrongAdminPassword
MYSQL_HOST=db
REDIS_HOST=redis
NEXTCLOUD_TRUSTED_DOMAINS=<IP>
EOF
```
**Create docker-compose**
```Bash
</> Bash
sudo tee docker-compose.yml > /dev/null << 'EOF'
version: '3.9'
services:
db:
image: mariadb:10.6
restart: always
env_file:
- .env
volumes:
- db_data:/var/lib/mysql
redis:
image: redis:7-alpine
restart: always
app:
image: nextcloud:apache
restart: always
ports:
- "8080:80"
env_file:
- .env
depends_on:
- db
- redis
volumes:
- nextcloud_data:/var/www/html
volumes:
db_data:
nextcloud_data:
EOF
```
**Start**
```Bash
</> Bash
docker compose up -d
```
**Validate**
```
http://<IP>:8080
```
### 3.11 Validate Internal Access
**Objective**
Confirm that the deployed Nextcloud instance is:
- Reachable over the network (via Droplet IP)
- Functionally operational (login, file operations)
- Persisting data correctly
- Stable prior to exposing externally
This is a hard validation gate—do not proceed until this passes.
**Test:**
- [ ] Login
- [ ] Upload file
- [ ] Create folder
- [ ] Restart containers
- [ ] Data persists
### 3.12 Install Nginx
**Objective**
Install and validate Nginx as the web server that will act as a reverse proxy in front of Nextcloud.
At the end of this step:
- Nginx is installed and running
- Port 80 (HTTP) is actively serving traffic
- Server is ready for reverse proxy configuration (Task 3.13)
```Bash
</> Bash
sudo apt install nginx -y
sudo systemctl enable nginx
sudo systemctl start nginx
```
**Test:**
```
http://<IP> → nginx welcome page
```
### 3.13 Configure HTTP Reverse Proxy (Staging Only)
**Objective**
Bind your domain to the application by configuring Nginx to proxy:
```
drive.company.com → Nginx (port 80) → Nextcloud (port 8080)
```
At the end of this step:
- Nginx reverse proxy configuration staged
- HTTP server block created for drive.company.com
- Nginx config syntax validates
- Nginx reloads successfully
- ⚠ Browser access may redirect to HTTPS and show 404 until SSL/HTTPS configuration is completed
```Bash
</> Bash
sudo tee /etc/nginx/sites-available/nextcloud > /dev/null << 'EOF'
server {
listen 80;
server_name drive.company.com;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto http;
}
}
EOF
```
**Enable:**
```Bash
</> Bash
sudo ln -s /etc/nginx/sites-available/nextcloud /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
```
*Important*
- ⚠ This step is NOT fully usable yet
- ⚠ HTTPS may redirect and show 404 (expected)
### 3.14 Install SSL (Certbot)
**Objective**
Obtain and install a valid SSL certificate so that:
https://drive.company.com
is:
- Trusted (no browser warnings)
- Encrypted (HTTPS)
- Routed through Nginx to Nextcloud
```Bash
</> Bash
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d drive.company.com
```
**Validate**
- ✔ Certificate issued
- ✔ HTTPS reachable
- ⚠ May still show 404 (expected)
### 3.15 Finalize HTTPS Reverse Proxy
**Objective**
Complete the system by:
- Wiring HTTPS (port 443) to Nextcloud
- Enforcing HTTP → HTTPS redirect
- Applying required Nextcloud proxy settings
- Performing end-to-end validation
At completion:
- https://drive.company.com fully functional
- Secure (SSL)
- Reverse proxy working
- Upload/download validated
**Replace config**
```Bash
</> Bash
sudo tee /etc/nginx/sites-available/nextcloud > /dev/null << 'EOF'
server {
listen 80;
server_name drive.company.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name drive.company.com;
ssl_certificate /etc/letsencrypt/live/drive.company.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/drive.company.com/privkey.pem;
client_max_body_size 10G;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
}
}
EOF
```
**Reload**
```Bash
</> Bash
sudo nginx -t
sudo systemctl reload nginx
```
**Fix Nextcloud**
```Bash
</> Bash
docker exec -u www-data nextcloud-app php occ config:system:set trusted_domains 1 --value="drive.company.com"
docker exec -u www-data nextcloud-app php occ config:system:set overwrite.cli.url --value="https://drive.company.com"
docker exec -u www-data nextcloud-app php occ config:system:set overwriteprotocol --value="https"
```
**Final Validation**
https://drive.company.com
- ✔ Login works
- ✔ Upload works
- ✔ Download works
- ✔ No warnings
- ✔ HTTPS padlock present
**Cleanup**
```Bash
</> Bash
sudo ufw delete allow 8080/tcp
```
✅ Final Outcome
- ✔ Secure Nextcloud deployment
- ✔ HTTPS reverse proxy functional
- ✔ Docker-based architecture
- ✔ Ready for users and workflows
### 3.16 Create Email Provider Account (Fastmail)
**Objective**
Establish a business-grade email platform using Fastmail so that:
- domain-based email (user@company.com)
- reliable outbound mail (for Nextcloud notifications later)
- foundation for SPF/DKIM/DMARC
**Architectural Context**
Email is not hosted on your droplet. Your infrastructure will later integrate with it for:
- Nextcloud notifications
- User accounts
- Client communication
**Prerequisites**
- Domain ownership confirmed
- Access to DNS registrar
- Decision: Fastmail selected (per runbook)
**Step 1 - Create Fastmail Account**
Go to: https://www.fastmail.com
1.1 Sign up
- Click Sign Up
- Choose a plan (Standard is sufficient for pilot)
- Enter:
```
Name
Email (temporary Fastmail domain)
Password
```
1.2 Complete account creation
You will land in the Fastmail admin interface.
**Step 2 - Add Your Domain**
2.1 Navigate to Domains
In Fastmail:
```
Settings → Domains → Add Domain
```
2.2 Enter your domain
```
company.com
```
Click:
```
Add Domain
```
**Step 3 - Verify Domain Ownership**
Fastmail will present a TXT verification record.
3.1 Copy TXT record
Example:
```
Type: TXT
Name: @
Value: fm-domain-verification=abc123xyz
```
3.2 Add to DNS (Registrar)
In your DNS provider (e.g., GoDaddy or Cloudflare):
Add:
```
Type: TXT
Host: @
Value: fm-domain-verification=abc123xyz
TTL: 300
```
3.3 Wait for propagation
```
~515 minutes typical, but may be as much as 24 hours
```
3.4 Verify in Fastmail
Click:
```
Verify Domain
```
Expected Result
- Domain verified successfully
**Step 4 - Set Domain as Default**
In Fastmail:
```
Settings → Domains → company.com → Set as default
```
This ensures:
- new users → user@company.com
**Step 5 - Create Initial Admin Mailbox**
5.1 Navigate to Users
```
Settings → Users → Add User
```
5.2 Create admin user
Example:
```
Username: admin
Email: admin@company.com
Password: (strong password)
```
5.3 Save
Expected Result
- Mailbox created
- Can send/receive (after DNS setup in 3.8)
**Step 6 - Basic Access Test (Pre-DNS)**
Login via:
```
https://app.fastmail.com
```
Expected
- Inbox accessible
- Account functional (even before MX setup)
- Email is NOT functional yet
**Validation Checklist**
- [✔] Fastmail account created
- [✔] Domain added to Fastmail
- [✔] TXT verification record created
- [✔] Domain verified
- [✔] Default domain set
- [✔] Admin mailbox created
- [✔] Able to login to Fastmail
### 3.17 Configure Email DNS
**Objective**
Make your domain fully capable of sending and receiving email by configuring DNS records required by Fastmail:
- Incoming mail routing (MX)
- Authorized senders (SPF)
- Cryptographic signing (DKIM)
- Policy & reporting (DMARC)
*Changing MX records WILL impact live email.*
If the client currently uses another provider:
- Schedule a cutover window
- Lower TTL beforehand (if possible)
- Expect brief delivery delays during propagation
**Prerequisites**
- Domain added & verified in Fastmail (Task 3.7)
- Access to DNS registrar
- Admin mailbox created
**Step 1 - Gather Fastmail DNS Records**
In Fastmail:
```
Settings → Domains → company.com → DNS Settings
```
Fastmail will provide all required records. Use those exact values if they differ from below.
**Step 2 - Configure MX Records (Mail Routing)**
2.1 Remove Existing MX Records
⚠️ Only do this at cutover time.
2.2 Add Fastmail MX Records
```
Type: MX
Host: @
Priority: 10
Value: in1-smtp.messagingengine.com
Type: MX
Host: @
Priority: 20
Value: in2-smtp.messagingengine.com
```
**Step 3 - Configure SPF (Sender Authorization)**
3.1 Add SPF record
```
Type: TXT
Host: @
Value: v=spf1 include:spf.messagingengine.com ~all
TTL: 300
```
Notes
- Only ONE SPF record per domain
- Merge with existing SPF if present
**Step 4 - Configure DKIM (Email Signing)**
4.1 Get DKIM from Fastmail
In Fastmail DNS settings, copy the DKIM record.
Example:
```
Type: CNAME
Host: fm1._domainkey
Value: fm1.company.com.dkim.fmhosted.com
Type: CNAME
Host: fm2._domainkey
Value: fm2.company.com.dkim.fmhosted.com
Type: CNAME
Host: fm3._domainkey
Value: fm3.company.com.dkim.fmhosted.com
4.2 Add all DKIM records
```
These enable:
- Email authenticity verification
- Better deliverability
**Step 5 - Configure DMARC (Policy & Reporting)**
5.1 Add DMARC record
```
Type: TXT
Host: _dmarc
Value: v=DMARC1; p=none; rua=mailto:admin@company.com
TTL: 300
```
Explanation
- p=none → monitor only (safe for pilot)
- rua= → aggregate reports sent to admin mailbox
Future Hardening
Later you can move to:
- p=quarantine → soft enforcement
- p=reject → full enforcement
**Step 6 - Verify DNS Propagation**
6.1 Check MX
nslookup -type=MX company.com
Expected:
in1-smtp.messagingengine.com
in2-smtp.messagingengine.com
6.2 Check SPF
nslookup -type=TXT company.com
6.3 Check DKIM
nslookup -type=CNAME fm1._domainkey.company.com
6.4 Check DMARC
nslookup -type=TXT _dmarc.company.com
**Step 7 - Functional Email Test**
7.1 Send inbound test
From Gmail/Outlook:
```
Send email to: admin@company.com
```
Expected:
- Email received in Fastmail inbox
7.2 Send outbound test
From Fastmail:
```
Send email to external address
```
Expected:
- Email delivered
- Not marked as spam
**Step 8 - Validate Deliverability (Recommended)**
Use:
- mail-tester.com
- mxtoolbox.com
Expected
- SPF pass
- DKIM pass
- DMARC pass
- Low spam score
**Step 9 - Propagation Expectations**
- MX: 530 minutes typical
- SPF: immediate to 1 hour
- DKIM: 1560 minutes
- DMARC: 1560 minutes
Worst case:
Up to 24 hours
**Validation Checklist**
- [✔] MX records updated
- [✔] SPF record present
- [✔] DKIM records configured (all 3)
- [✔] DMARC record created
- [✔] DNS resolves correctly
- [✔] Email received externally
- [✔] Email sent externally
- [✔] Deliverability validated
### 3.18 Create Email Accounts
**Objective**
Provision internal user mailboxes in Fastmail so that:
- Each employee has a company email (user@company.com)
- Accounts align with Nextcloud users (identity consistency)
- System ready for communication + notifications
**Architectural Context**
User identity is now split across:
- Fastmail → Email identity (user@company.com)
- Nextcloud → Application access (files, shares)
**Step 1 - Define User List**
Before creating accounts, confirm:
| Name | Email Address |
|-------|-----|
| John Smith | jsmith@company.com |
| Jane Doe | jdoe@company.com |
| Operations | ops@company.com |
Best Practices
- Use simple, consistent naming (first initial + last name)
- Avoid special characters
- Reserve generic aliases (admin, info, support)
**Step 2 - Access User Management**
In Fastmail:
```
Settings → Users → Add User
```
**Step 3 - Create Individual User Accounts
3.1 Enter user details
For each user:
```
Username: jsmith
Email: jsmith@company.com
Full Name: John Smith
Password: (temporary strong password)
```
3.2 Set password policy
- Use strong temporary password
- Require user to change on first login (recommended)
3.3 Save user
Repeat for all internal users.
**Step 4 - Assign Roles & Permissions**
Default (Recommended for Pilot)
- Standard User (no admin privileges)
Admin Accounts
Only assign admin rights to:
- System owner
- IT/consultant (if required)
**Step 5 - Create Aliases (Optional but Recommended)**
Common aliases
```
admin@company.com
info@company.com
support@company.com
```
How to create
In Fastmail:
```
Settings → Domains → company.com → Aliases
```
Example
support@company.com → jsmith@company.com
**Step 6 - Validate Each Account**
6.1 Login test
```
https://app.fastmail.com
```
6.2 Send test email
- Send to another internal user
- Send to external address (e.g., Gmail)
6.3 Receive test email
- Receive from external sender
- Confirm inbox delivery
**Step 7 - Distribute Credentials**
For each user, provide:
- Email address
- Temporary password
- Login URL: https://app.fastmail.com
- Instructions to change password
**Validation Checklist**
- [✔] All internal users created
- [✔] Email addresses correct
- [✔] Login verified for each user
- [✔] Send/receive tested
- [✔] Aliases created (if needed)
- [✔] Credentials distributed securely
- [✔] Usernames aligned with Nextcloud
### 3.19 Create Nextcloud Users
Objective
Provision user accounts in Nextcloud aligned with your email identities so that:
✔ Each internal user has access to the platform
✔ Identity is consistent across email and Nextcloud
✔ Permissions can be assigned cleanly in later steps
Architectural Context
You now have:
Fastmail → user@company.com (email identity)
Nextcloud → username (application identity)
For this pilot:
✔ Keep usernames identical (jsmith ↔ jsmith@company.com)
Prerequisites
[✔] Nextcloud deployed and accessible (Task 3.15)
[✔] HTTPS working: https://drive.company.com
[✔] Admin account available
[✔] Email accounts created (Task 3.18)
🌐 Step 1 — Log into Nextcloud as Admin
Open:
https://drive.company.com
Login:
Username: admin
Password: (from .env)
⚙️ Step 2 — Navigate to User Management
In Nextcloud UI:
Top-right avatar → Users
Step 3 — Create Users
3.1 Enter user details
For each user:
Username: jsmith
Display Name: John Smith
Email: jsmith@company.com
Password: (temporary strong password)
3.2 Assign groups (recommended)
Create group:
internal
Assign all internal users to this group.
3.3 Save user
Repeat for all internal users.
🔐 Step 4 — Set Password Policy
Recommended
✔ Strong temporary passwords
✔ Users change password on first login
🧪 Step 5 — Validate User Access
5.1 Login test (per user)
Open new browser/private window:
https://drive.company.com
Login as user:
✔ Successful login
✔ Dashboard loads
5.2 Basic file test
As user:
✔ Upload file
✔ Create folder
✔ Delete file
🔄 Step 6 — Verify Admin Visibility
Return to admin account:
✔ All users listed
✔ Group assignments correct
✔ No duplicate usernames
📧 Step 7 — (Optional) Configure Email Field
Ensure each user has email set:
jsmith → jsmith@company.com
Why this matters
✔ Enables sharing notifications
✔ Required for password reset
✔ Supports future SMTP integration
🧠 Step 8 — Naming Consistency Check
Ensure alignment:
Email: jsmith@company.com
Nextcloud: jsmith
Avoid
✖ john.smith in one system and jsmith in another
🔒 Step 9 — Security Considerations
Enforce
✔ Unique user accounts (no sharing)
✔ Strong passwords
✔ Minimal admin users
Optional (future)
✔ Enable 2FA in Nextcloud
✔ Integrate SSO (future phase)
✅ Validation Checklist
[✔] All users created in Nextcloud
[✔] Usernames match email identities
[✔] Users can log in successfully
[✔] File operations work for each user
[✔] Groups assigned correctly
[✔] Emails populated in profiles