Add infra/ with student-vms OpenTofu root module
- infra/pve: host facts, IP plan, one-time setup - infra/tofu/student-vms: 3 student VMs via tf-mod-pve v1.0.0 - infra/sandbox: template clones for throwaway test VMs - README/TODO: Windows DC/AD instead of FreeIPA, new network - .gitignore: only ignore secrets.auto.tfvars instead of all tfvars Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
2dfa8de5c6
commit
91ed0b300c
12 files changed
+194
-41
No files matched your search
+2
-6
@@ -13,12 +13,8 @@
|
||||
crash.log
|
||||
crash.*.log
|
||||
|
||||
# Exclude all .tfvars files, which are likely to contain sensitive data, such as
|
||||
# password, private keys, and other secrets. These should not be part of version
|
||||
# control as they are data points which are potentially sensitive and subject
|
||||
# to change depending on the environment.
|
||||
*.tfvars
|
||||
*.tfvars.json
|
||||
# Secrets (API token, SSH user); see secrets.auto.tfvars.example
|
||||
secrets.auto.tfvars
|
||||
|
||||
# Ignore override files as they are usually used to override resources locally and so
|
||||
# are not checked in
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
# Learning Plattform for Students
|
||||
# Learning Platform for Students
|
||||
|
||||
## init
|
||||
|
||||
@@ -21,47 +21,32 @@ Build a reliable platform on a pve host to teach students Linux/Windows server a
|
||||
|
||||
## User Management
|
||||
|
||||
Apart from the pve host, the main core of the environment will be a _FreeIPA_ Server which combines
|
||||
A Windows Server DC/AD is the identity and DNS server of the lab. Each student gets an AD account and is in the group `linux_students` (further groups: `linux_admins`, `linux_users`). Student VMs join the domain.
|
||||
|
||||
- identity management server (ldap, sso, acl, ...) via a 389 directory server
|
||||
- DNS server (bind)
|
||||
- NTP server
|
||||
- Kerberos
|
||||
- Dogtag for certificate management
|
||||
- NFS server or 'advertise' one for home folders of all users and other userful shares when needed in an exercise
|
||||
Additional DCs and firewalls/routers are built by the students as exercises.
|
||||
|
||||
## Repo layout
|
||||
|
||||
We will setup user accounts for each student on the ipa server and a home folder for each one which are shared via nfs
|
||||
and automatically mounted on user login on any device in the domain/realm.
|
||||
The student will always have their files available no matter the device they login with their own account.
|
||||
|
||||
Define designated groups, `linux_admins`, `linux_students`, `linux_users`, with each its own ACLs mediated via the ipa server.
|
||||
|
||||
- `exercises/`: exercise sheets
|
||||
- `infra/pve/`: PVE host facts, IP plan, one-time setup
|
||||
- `infra/tofu/<role>/`: one OpenTofu root module (and state) per role, e.g. `student-vms`
|
||||
- `infra/sandbox/`: throwaway test VMs (template clones, no OpenTofu)
|
||||
|
||||
## Facts
|
||||
|
||||
**Domain:**
|
||||
|
||||
- domain: `lab.softbox.net`
|
||||
- realm: `LAB.SOFTBOX.NET`
|
||||
- ipa:
|
||||
- hostname: `ipa.lab.softox.net`
|
||||
- ip address: `10.11.12.65/24`
|
||||
|
||||
**Domain:** `lab.softbox.net`
|
||||
|
||||
**Students:**
|
||||
|
||||
- username: `firstname.surname`
|
||||
- mail: `firstname.surname@softbox.de`
|
||||
- user_ssh_public_key: Created in exercise sheet-00
|
||||
- uid: `1000-1020`
|
||||
- gid: `1000-1020`
|
||||
- user_ssh_public_key: created in exercise sheet-00
|
||||
- groups: `linux_students`
|
||||
|
||||
**VMs:**
|
||||
|
||||
- hostname: `vm_00`
|
||||
- IP addresses: `10.11.12.200-220`
|
||||
- hostname: `vm-00` … `vm-20`
|
||||
- IP addresses: `10.100.200.80-100` (see [infra/pve/README.md](infra/pve/README.md))
|
||||
|
||||
## Schedule
|
||||
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
## TODOs
|
||||
|
||||
- [ ] change hostnames and correspondingly the dns entries of the student hosts to `vm_00` -> manage dns via opentofu
|
||||
- [ ] include all users to freeipa and integrate freeipa as main identity and dns server. Deprecate current bind servers -> automate client installation
|
||||
- [ ] migrate dns zone to freeipa and manage its bind server with opentofu
|
||||
- [ ] create nfs shares for the home folder of each user
|
||||
- [ ] write loop for student_vm deployment -> they are similar
|
||||
|
||||
- [ ] include automation which install freeipa-client on each vm via opentofu or ansible executed via opentofu
|
||||
- [ ] set up the Windows DC/AD `dc01` (`10.100.200.70`, 2 vCPU, 4-8 GB) as identity and DNS server
|
||||
- [ ] switch the student VMs' DNS to the DC and join them to the domain
|
||||
- [ ] create AD accounts and home folders for all students
|
||||
- [ ] write nice markdown template for sheets. With better code highlighting and better text formatting
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
# PVE host
|
||||
|
||||
- Host: `pve` (`10.100.200.50`), Proxmox VE 9.2, 6 cores, 31 GiB RAM
|
||||
- Storage: `local` (dir: ISOs, snippets), `local-lvm` (VM disks)
|
||||
- Network: `vmbr0` on `10.100.200.0/24`, gateway and current DNS `10.100.200.4`
|
||||
- Templates: `903` `temp-debian-13`
|
||||
|
||||
## IP plan (10.100.200.0/24)
|
||||
|
||||
| Address | Use | Size |
|
||||
|---|---|---|
|
||||
| `.4` | Gateway, current DNS | |
|
||||
| `.50` | PVE host | |
|
||||
| `.70` | DC/AD `dc01.lab.softbox.net` (planned) | 2 vCPU, 4-8 GB |
|
||||
| `.80-.100` | Student VMs (`vm-00`, …), VMID `1080-1100`, 5-10 planned | 1 vCPU, 1 GB |
|
||||
| `.101-.211` | In use by other devices (probably DHCP) | |
|
||||
|
||||
## One-time setup (as root, done)
|
||||
|
||||
```bash
|
||||
# 1. Allow snippets on local storage
|
||||
pvesm set local --content iso,vztmpl,backup,import,snippets
|
||||
|
||||
# 2. API user and token for OpenTofu; put the printed value into
|
||||
# infra/tofu/<role>/secrets.auto.tfvars as pve_api_token = "tofu@pve!tofu=<value>"
|
||||
pveum user add tofu@pve --comment "OpenTofu"
|
||||
pveum aclmod / -user tofu@pve -role PVEAdmin
|
||||
pveum user token add tofu@pve tofu --privsep 0
|
||||
|
||||
# 3. sudo for sbxadmin; passwordless rules for the snippet upload of the bpg/proxmox provider
|
||||
usermod -aG sudo sbxadmin
|
||||
cat > /etc/sudoers.d/sbxadmin-tofu <<'EOF'
|
||||
sbxadmin ALL=(root) NOPASSWD: /usr/sbin/pvesm apiinfo
|
||||
sbxadmin ALL=(root) NOPASSWD: /usr/bin/tee ^/var/lib/vz/snippets/[a-zA-Z0-9_][a-zA-Z0-9_.-]*$
|
||||
EOF
|
||||
chmod 440 /etc/sudoers.d/sbxadmin-tofu && visudo -c
|
||||
|
||||
# 4. Templates: tf-mod-pve/scripts/create_template.sh, copied to /root/templates/ with
|
||||
# storage=local-lvm, ssh_keyfile=/root/.ssh/authorized_keys, only temp-debian-13 enabled
|
||||
cd /root/templates && bash create_template.sh
|
||||
```
|
||||
@@ -0,0 +1,13 @@
|
||||
# sandbox
|
||||
|
||||
Throwaway test VMs, not managed by OpenTofu. Clone a template on the PVE host (as root), use VMIDs `9990-9999`:
|
||||
|
||||
```bash
|
||||
qm clone 903 9991 --name test-01 --full
|
||||
qm set 9991 --ipconfig0 ip=dhcp
|
||||
qm start 9991
|
||||
# done testing
|
||||
qm stop 9991 && qm destroy 9991
|
||||
```
|
||||
|
||||
Login: `ssh admin@<ip>` (IP via `qm guest cmd 9991 network-get-interfaces`).
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
# This file is maintained automatically by "tofu init".
|
||||
# Manual edits may be lost in future updates.
|
||||
|
||||
provider "registry.opentofu.org/bpg/proxmox" {
|
||||
version = "0.118.1"
|
||||
constraints = ">= 0.118.0, ~> 0.118"
|
||||
hashes = [
|
||||
"h1:/tyENGiIdJgBVlcOQOyHaBmLyQEoogFnTTMN+GJ6ayE=",
|
||||
"h1:057hFYAlLv2HcjHR7TVoNnDmm57YWNZDNqhDvv6PS7I=",
|
||||
"h1:CxLdcddSmTqP00oYkvWdN6d+qQSDTOhDzbM2/FzCPbY=",
|
||||
"h1:E1uc/cddGUBfnYyLOxnmqpzd6yLL4RKHqZJVxRMn/DA=",
|
||||
"h1:G34GMrwG/FejGMTxwJYKx4tghadFA+xqtrF40FbyOG8=",
|
||||
"h1:M1nzf28WMPzm4p9sUJGrAUOcqfDyQwRjRIpFMaHzo+Q=",
|
||||
"h1:MeUGboRbtAzb07dgljVCzUmU5hJ8BOfHBQOOtFzNziU=",
|
||||
"h1:OCF6iuMldDOqn52ULPf22IJb0Ni3GFx6HdoiTAPIb3M=",
|
||||
"h1:f46bI0fO0leCFEkYdEVcRrsjAAtSFEN6yZKu2fZymTI=",
|
||||
"h1:fhAY0NwBwBBu/qUeTb1lAd3a7bffgouILhhjUNNNXCk=",
|
||||
"h1:gaCA8Ez8zV/OXIVWIE1B11iQmKH7gILdn7Vm9KSRrbU=",
|
||||
"h1:r52a2cEQ7ftGS1G6vHFMqWI6Bg6o0F/T5BsShH8O2DQ=",
|
||||
"h1:wAD5hFQpgEptQYR5UK8Hbh8WoTcMGnRCxehLqN+3f9w=",
|
||||
"zh:07405857f3dda91d1a065b0349547920f4f9b58ec214b19f7e54a07d776c1f88",
|
||||
"zh:0bd362db77c5971fe0e92b0faf57ed9b50062d4321b5c7a09f492c57dffecb19",
|
||||
"zh:2cb31f9d4ad2ae90f72f87e3cb77c2f745acbe4b17822821c385612647ea178d",
|
||||
"zh:2e63ff741101e173feafb133f96273634831322984939115396763b6f860706b",
|
||||
"zh:787bdda1b4e0924c334acebeb7491966b8e611aaa8e542ec003cb8cbfd9081f4",
|
||||
"zh:7f2ece41d81a24988f5a357684b2b323cc5165022434e7f91e5a29f10a4182c7",
|
||||
"zh:9a1e263e4111105c14ed1dc44a5c4e45f00f0f88cb726d16388771c1cdd9b26d",
|
||||
"zh:a2c1ae4950667bdc0f023f3d12d175fec3cf1a809c4d990cf72f0a200606f6f8",
|
||||
"zh:abd342c9153e712a8542b0fd03f6a0b25f954573184dfe8f5b05b08b1e26e254",
|
||||
"zh:b5cc543d31183a63c782af7fab9a4a203b4eebf782db13af94ae65c9b7d51373",
|
||||
"zh:befeb50e7346802d3c222541e91a06093933990acdfc89cf93364615fdac91c4",
|
||||
"zh:d164da80b3f3339549942a3131b0717f14798ed514e8362c76874b68feba89f8",
|
||||
"zh:dc265c6e4c3e656e014c524b50e0ff02761070cb9db7cb24f7b0ab57c12b9e97",
|
||||
"zh:f26e0763dbe6a6b2195c94b44696f2110f7f55433dc142839be16b9697fa5597",
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
# student-vms
|
||||
|
||||
One Debian 13 VM per student (`vm-00`, `vm-01`, …, IPs `10.100.200.80-100`), created with [tf-mod-pve](https://github.com/CubelaPetar/tf-mod-pve). The VM list is in `vms.tf`.
|
||||
|
||||
Prerequisites: host setup from [`../../pve/README.md`](../../pve/README.md) and your SSH key authorized for `sbxadmin` on the host.
|
||||
|
||||
```bash
|
||||
ssh-add ~/.ssh/id_ed25519 # provider uploads snippets via ssh-agent
|
||||
cp secrets.auto.tfvars.example secrets.auto.tfvars # fill in the API token
|
||||
tofu init
|
||||
tofu plan
|
||||
tofu apply
|
||||
```
|
||||
|
||||
State is local (`terraform.tfstate`, gitignored). Back it up.
|
||||
@@ -0,0 +1,11 @@
|
||||
provider "proxmox" {
|
||||
endpoint = "https://10.100.200.50:8006/"
|
||||
api_token = var.pve_api_token
|
||||
insecure = true # self-signed certificate
|
||||
|
||||
# Used to upload the cloud-init snippets, key comes from the ssh-agent
|
||||
ssh {
|
||||
agent = true
|
||||
username = var.pve_ssh_user
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
# Copy to secrets.auto.tfvars (gitignored) and fill in
|
||||
pve_api_token = "tofu@pve!tofu=<secret>"
|
||||
pve_ssh_user = "sbxadmin"
|
||||
@@ -0,0 +1,16 @@
|
||||
variable "pve_api_token" {
|
||||
type = string
|
||||
description = "Proxmox API token, e.g. tofu@pve!tofu=<secret>"
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "pve_ssh_user" {
|
||||
type = string
|
||||
description = "SSH user on the PVE host for the snippet upload"
|
||||
}
|
||||
|
||||
variable "ssh_public_key_file" {
|
||||
type = string
|
||||
description = "Public key added to the VM user admin"
|
||||
default = "~/.ssh/id_ed25519.pub"
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
terraform {
|
||||
required_version = ">= 1.10"
|
||||
|
||||
required_providers {
|
||||
proxmox = {
|
||||
source = "bpg/proxmox"
|
||||
version = "~> 0.118"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
# One VM per student: hostname => VMID and IP (10.100.200.80-100)
|
||||
locals {
|
||||
vms = {
|
||||
"vm-00" = { vm_id = 1080, ip = "10.100.200.80" }
|
||||
"vm-01" = { vm_id = 1081, ip = "10.100.200.81" }
|
||||
"vm-02" = { vm_id = 1082, ip = "10.100.200.82" }
|
||||
}
|
||||
}
|
||||
|
||||
module "vm" {
|
||||
source = "git::https://github.com/CubelaPetar/tf-mod-pve.git?ref=v1.0.0"
|
||||
for_each = local.vms
|
||||
|
||||
node_name = "pve"
|
||||
vm_id = each.value.vm_id
|
||||
template_vm_id = 903 # temp-debian-13
|
||||
hostname = each.key
|
||||
domain = "lab.softbox.net"
|
||||
tags = ["student"]
|
||||
ssh_public_key = file(pathexpand(var.ssh_public_key_file))
|
||||
|
||||
cpu_cores = 1
|
||||
memory = 1024
|
||||
storage = "local-lvm"
|
||||
disk_size = 16
|
||||
|
||||
net_bridge = "vmbr0"
|
||||
ip_address = "${each.value.ip}/24"
|
||||
gateway = "10.100.200.4"
|
||||
# Current resolver until the DC/AD takes over DNS
|
||||
nameservers = ["10.100.200.4"]
|
||||
}
|
||||
Reference in new issue
Block a user