-
Notifications
You must be signed in to change notification settings - Fork 0
178 lines (158 loc) · 7.77 KB
/
Copy pathdeploy.yml
File metadata and controls
178 lines (158 loc) · 7.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
name: Deploy
on:
workflow_dispatch:
inputs:
target_host:
description: "Target host IP or FQDN to deploy to"
required: true
type: string
hostname:
description: "Short hostname to configure on the target"
required: true
type: string
fqdn:
description: "Fully qualified domain name to configure on the target"
required: true
type: string
skip_base_setup:
description: "Skip base setup stage"
type: boolean
default: false
skip_ad_join:
description: "Skip AD join stage"
type: boolean
default: false
skip_satellite:
description: "Skip Satellite registration stage"
type: boolean
default: false
skip_ad_rejoin_cron:
description: "Skip AD rejoin cron stage"
type: boolean
default: false
jobs:
lint:
name: Lint
uses: ./.github/workflows/lint.yml
deploy:
name: Deploy to ${{ inputs.target_host }}
needs: lint
runs-on: ubuntu-latest
# Requires a 'production' environment to be configured in GitHub with
# required reviewers, preventing unreviewed deploys.
# Settings > Environments > production
environment: production
# All GitHub Actions expressions are resolved here into plain shell
# variables, keeping run: blocks free of ${{ }} and ShellCheck-clean.
env:
SSH_PORT: ${{ vars.SSH_PORT || '22' }}
DEPLOY_TARGET: ${{ vars.DEPLOY_USER }}@${{ inputs.target_host }}
TARGET_HOST: ${{ inputs.target_host }}
KNOWN_HOST: ${{ vars.DEPLOY_KNOWN_HOST }}
# Variables passed to deploy.sh on the target host
TARGET_HOSTNAME: ${{ inputs.hostname }}
TARGET_FQDN: ${{ inputs.fqdn }}
ADMIN_USER: ${{ vars.ADMIN_USER }}
ADMIN_SSH_KEY: ${{ vars.ADMIN_SSH_KEY }}
NTP_SERVERS: ${{ vars.NTP_SERVERS }}
FIREWALL_EXTRA_SERVICES: ${{ vars.FIREWALL_EXTRA_SERVICES }}
LOGIN_BANNER: ${{ vars.LOGIN_BANNER }}
AD_DOMAIN: ${{ vars.AD_DOMAIN }}
AD_SERVER: ${{ vars.AD_SERVER }}
KRB5_REALM: ${{ vars.KRB5_REALM }}
AD_JOIN_USER: ${{ vars.AD_JOIN_USER }}
AD_JOIN_PASS: ${{ secrets.AD_JOIN_PASS }}
SATELLITE_SERVER: ${{ vars.SATELLITE_SERVER }}
SATELLITE_ORG: ${{ vars.SATELLITE_ORG }}
SATELLITE_ACTIVATION_KEY: ${{ secrets.SATELLITE_ACTIVATION_KEY }}
SATELLITE_ENV: ${{ vars.SATELLITE_ENV }}
WHEEL_USER: ${{ vars.WHEEL_USER }}
REJOIN_SCRIPT: ${{ vars.REJOIN_SCRIPT }}
SKIP_BASE_SETUP: ${{ inputs.skip_base_setup }}
SKIP_AD_JOIN: ${{ inputs.skip_ad_join }}
SKIP_SATELLITE: ${{ inputs.skip_satellite }}
SKIP_AD_REJOIN_CRON: ${{ inputs.skip_ad_rejoin_cron }}
steps:
- uses: actions/checkout@v4
# ── SSH setup ────────────────────────────────────────────────────────────
- name: Configure SSH
run: |
mkdir -p ~/.ssh
chmod 700 ~/.ssh
echo "${DEPLOY_SSH_KEY}" > ~/.ssh/deploy_key
chmod 600 ~/.ssh/deploy_key
# Prefer a stored known_hosts entry (avoids MITM risk of blind keyscan).
# Set DEPLOY_KNOWN_HOST in GitHub Actions variables using the output of:
# ssh-keyscan <target_host>
# If not set, fall back to keyscan (acceptable for first-time bootstrapping).
if [[ -n "${KNOWN_HOST}" ]]; then
echo "${KNOWN_HOST}" >> ~/.ssh/known_hosts
else
echo "WARNING: DEPLOY_KNOWN_HOST not set, falling back to ssh-keyscan." >&2
ssh-keyscan -p "${SSH_PORT}" -H "${TARGET_HOST}" >> ~/.ssh/known_hosts
fi
chmod 600 ~/.ssh/known_hosts
env:
DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
# ── Copy scripts to target ───────────────────────────────────────────────
- name: Copy scripts to target host
run: |
rsync -az --delete \
-e "ssh -i ~/.ssh/deploy_key -p ${SSH_PORT}" \
scripts/ config/ \
"${DEPLOY_TARGET}:/opt/linuxconfig/"
# ── Write env file to tmpfs on target ────────────────────────────────────
#
# The env file is written on the ephemeral runner, then copied via scp to
# /dev/shm on the target (tmpfs — never written to disk). The local copy
# is removed immediately after transfer. The remote copy is shredded in
# the cleanup step, which runs even if the deploy fails.
- name: Write env file to target tmpfs
run: |
# Build the env file locally on the ephemeral runner. All variables
# are already resolved by the job env: block above.
{
echo "# Auto-generated by deploy workflow — do not edit"
echo "export HOSTNAME=\"${TARGET_HOSTNAME}\""
echo "export FQDN=\"${TARGET_FQDN}\""
echo "export ADMIN_USER=\"${ADMIN_USER}\""
echo "export ADMIN_SSH_KEY=\"${ADMIN_SSH_KEY}\""
echo "export SSH_PORT=\"${SSH_PORT}\""
echo "export NTP_SERVERS=\"${NTP_SERVERS}\""
echo "export FIREWALL_EXTRA_SERVICES=\"${FIREWALL_EXTRA_SERVICES}\""
echo "export LOGIN_BANNER=\"${LOGIN_BANNER}\""
echo "export AD_DOMAIN=\"${AD_DOMAIN}\""
echo "export AD_SERVER=\"${AD_SERVER}\""
echo "export KRB5_REALM=\"${KRB5_REALM}\""
echo "export AD_JOIN_USER=\"${AD_JOIN_USER}\""
echo "export AD_JOIN_PASS=\"${AD_JOIN_PASS}\""
echo "export SATELLITE_SERVER=\"${SATELLITE_SERVER}\""
echo "export SATELLITE_ORG=\"${SATELLITE_ORG}\""
echo "export SATELLITE_ACTIVATION_KEY=\"${SATELLITE_ACTIVATION_KEY}\""
echo "export SATELLITE_ENV=\"${SATELLITE_ENV}\""
echo "export WHEEL_USER=\"${WHEEL_USER}\""
echo "export REJOIN_SCRIPT=\"${REJOIN_SCRIPT}\""
echo "export SKIP_BASE_SETUP=\"${SKIP_BASE_SETUP}\""
echo "export SKIP_AD_JOIN=\"${SKIP_AD_JOIN}\""
echo "export SKIP_SATELLITE=\"${SKIP_SATELLITE}\""
echo "export SKIP_AD_REJOIN_CRON=\"${SKIP_AD_REJOIN_CRON}\""
} > /tmp/deploy.env
chmod 600 /tmp/deploy.env
# Copy to remote tmpfs and remove local copy
scp -i ~/.ssh/deploy_key -P "${SSH_PORT}" \
/tmp/deploy.env \
"${DEPLOY_TARGET}:/dev/shm/.deploy.env"
ssh -i ~/.ssh/deploy_key -p "${SSH_PORT}" "${DEPLOY_TARGET}" \
"chmod 600 /dev/shm/.deploy.env"
rm -f /tmp/deploy.env
# ── Deploy ───────────────────────────────────────────────────────────────
- name: Run deploy.sh
run: |
ssh -i ~/.ssh/deploy_key -p "${SSH_PORT}" "${DEPLOY_TARGET}" \
"source /dev/shm/.deploy.env && sudo -E bash /opt/linuxconfig/scripts/deploy.sh"
# ── Cleanup ──────────────────────────────────────────────────────────────
- name: Remove env file from target
if: always()
run: |
ssh -i ~/.ssh/deploy_key -p "${SSH_PORT}" "${DEPLOY_TARGET}" \
"shred -u /dev/shm/.deploy.env 2>/dev/null || true"