−25%

kwa Windows ya mwaka, hadi 31 Okt. Tazama mipango

EQVPS
Anza

VPS kwa maonyesho ya awali ya mawakala wa kuandika msimbo: kila tawi analosukuma wakala linapata URL yake

Wakala wa kuandika msimbo amemaliza tawi na anasema linafanya kazi. Mpe seva ambapo hilo linaweza kukaguliwa: kila tawi linajengwa kuwa kontena na kufunguka kwenye kikoa kidogo chake cha HTTPS nyuma ya nenosiri, na ufunguo wa SSH wa wakala unaweza tu kuwasha na kuzima maonyesho ya awali.

Wakala wa kuandika msimbo anasema kipengele kinafanya kazi. Labda ni kweli. Majaribio aliyoandika yanapita, na hilo linathibitisha machache kuliko tungependa sote. Unachotaka hasa ni kukifungua kwenye kivinjari kabla hakijakaribia watumiaji, na kufanya hivyo bila kumwomba wakala aguse uzalishaji.

Mazingira ya onyesho la awali hutatua hilo, na huhitaji jukwaa kwa ajili yake. VPS moja yenye IPv4 yake, Docker, Caddy na hati mbili fupi hupa kila tawi URL yake kama https://feature-login-form.preview.example.com, nyuma ya nenosiri, likijengwa upya kila push. Wakala hupata ufunguo wa SSH unaoweza kuwasha na kuzima maonyesho ya awali na si zaidi.

Tulijenga hili kwenye seva ya majaribio na kupitia mzunguko mzima kabla ya kuliandika: kuunda, kufungua, push tena, kuondoa, na kujaribu kutumia ufunguo vibaya.

Unachohitaji

  • VPS yenye IPv4 ya umma. AI-Agent-IP ina nafasi kwa maonyesho kadhaa kwa wakati mmoja.
  • Rekodi ya DNS ya wildcard: *.preview.example.com → IP ya seva.
  • Hazina ya programu yako yenye Dockerfile inayohudumia kwenye mlango 8080. Lugha yoyote inafaa.
  • Ubuntu 24.04 au Debian 12/13 pamoja na apt install -y docker.io caddy git.

Nakili hazina mara moja kwenda /srv/app kwa ufunguo wa deploy wa kusoma tu.

Hati mbili

/usr/local/bin/preview-up hujenga tawi na kuliweka mtandaoni:

#!/usr/bin/env bash
# preview-up <branch> — build the branch and open it at https://<name>.preview.example.com
set -euo pipefail
BRANCH="$1"
NAME=$(printf '%s' "$BRANCH" | tr '[:upper:]' '[:lower:]' | tr -c 'a-z0-9' '-' | sed 's/--*/-/g; s/^-//; s/-$//' | cut -c1-40)
DIR=/srv/previews/$NAME
git -C /srv/app fetch --quiet origin "$BRANCH"
rm -rf "$DIR"; git -C /srv/app worktree prune
git -C /srv/app worktree add --quiet --force --detach "$DIR" FETCH_HEAD
docker build --quiet -t "preview-$NAME" "$DIR" >/dev/null
docker rm -f "preview-$NAME" >/dev/null 2>&1 || true
docker run -d --name "preview-$NAME" --restart unless-stopped --memory 512m -p 127.0.0.1::8080 "preview-$NAME" >/dev/null
PORT=$(docker port "preview-$NAME" 8080/tcp | head -1 | awk -F: '{print $NF}')
cat > "/etc/caddy/previews/$NAME.caddy" <<CADDY
$NAME.preview.example.com {
	import preview_common
	reverse_proxy 127.0.0.1:$PORT
}
CADDY
systemctl reload caddy
echo "https://$NAME.preview.example.com"

/usr/local/bin/preview-down huliondoa:

#!/usr/bin/env bash
# preview-down <branch> — remove the branch preview
set -euo pipefail
NAME=$(printf '%s' "$1" | tr '[:upper:]' '[:lower:]' | tr -c 'a-z0-9' '-' | sed 's/--*/-/g; s/^-//; s/-$//' | cut -c1-40)
docker rm -f "preview-$NAME" >/dev/null 2>&1 || true
docker image rm "preview-$NAME" >/dev/null 2>&1 || true
rm -f "/etc/caddy/previews/$NAME.caddy"; rm -rf "/srv/previews/$NAME"; git -C /srv/app worktree prune
systemctl reload caddy

Baadhi ya machaguo humo ni ya makusudi. Kontena huchapishwa kwenye 127.0.0.1 tu kwa mlango wa nasibu, kwa hiyo hakuna kinachoyafikia isipokuwa kupitia Caddy. Hilo ni muhimu kwa sababu milango inayochapishwa na Docker hupita ufw. Kila onyesho la awali lina kikomo cha kumbukumbu cha 512 MB, ili tawi moja lisilodhibitiwa lisiyaangushe mengine. Na kuendesha tawi lile lile tena hulijenga upya pale pale: push, endesha up, onyesha upya.

Caddy: faili moja kwa kila onyesho, nenosiri moja kwa yote

mkdir -p /etc/caddy/previews /srv/previews
chmod +x /usr/local/bin/preview-up /usr/local/bin/preview-down
caddy hash-password --plaintext 'choose-a-review-password'

Weka hash kwenye /etc/caddy/Caddyfile:

(preview_common) {
	basicauth {
		reviewer PASTE-THE-HASH-HERE
	}
}
import /etc/caddy/previews/*.caddy

Kisha systemctl reload caddy. Sasa kila onyesho la awali liko nyuma ya kuingia kule kule, kwa hiyo tawi lililokamilika nusu lenye matokeo ya utatuzi halibaki wazi kwenye intaneti. Katika matoleo mapya ya Caddy agizo hili pia huandikwa basic_auth; basicauth bado hufanya kazi kwenye yote mawili.

Ufunguo wa wakala: up na down, si zaidi

Wakala anahitaji kuwasha maonyesho ya awali, si kumiliki seva. Unda mtumiaji deploy na hati ya lango inayokubali amri mbili hasa:

#!/usr/bin/env bash
# /usr/local/bin/preview-gate — the only thing the agent's key may run
set -euo pipefail
read -r ACTION BRANCH EXTRA <<< "${SSH_ORIGINAL_COMMAND:-}"
[[ -z "${EXTRA:-}" && "${BRANCH:-}" =~ ^[A-Za-z0-9][A-Za-z0-9._/-]{0,99}$ && "$BRANCH" != *..* ]] || { echo "usage: up|down <branch>" >&2; exit 2; }
case "$ACTION" in
  up)   exec sudo /usr/local/bin/preview-up "$BRANCH" ;;
  down) exec sudo /usr/local/bin/preview-down "$BRANCH" ;;
  *)    echo "usage: up|down <branch>" >&2; exit 2 ;;
esac
useradd -m -s /bin/bash deploy
echo 'deploy ALL=(root) NOPASSWD: /usr/local/bin/preview-up, /usr/local/bin/preview-down' > /etc/sudoers.d/preview
chmod 440 /etc/sudoers.d/preview && visudo -cf /etc/sudoers.d/preview
chmod 755 /usr/local/bin/preview-gate

Kwenye /home/deploy/.ssh/authorized_keys, funga ufunguo wa umma wa wakala kwenye hati hiyo:

restrict,command="/usr/local/bin/preview-gate" ssh-ed25519 AAAA... coding-agent

Kutoka kwa mashine anayofanyia kazi wakala:

ssh deploy@preview.example.com up feature/login-form
# https://feature-login-form.preview.example.com
ssh deploy@preview.example.com down feature/login-form

Kwenye jaribio letu, up ilijenga na kuchapisha tawi, up ya pili baada ya commit mpya ilitoa toleo jipya, na down iliondoa kontena na tovuti. Majaribio ya cat /etc/shadow, up x; id, majina ya matawi kama -x au a/../b, au kuingia kwa mwingiliano kwa ufunguo huo yote yalipata usage: up|down <branch> tu. Jina la tawi lazima lianze kwa herufi au tarakimu na haliwezi kuwa na ...

Kuliunganisha na wakala

Kwa Claude Code au Codex, mstari mmoja kwenye faili ya maelekezo ya mradi unatosha:

Baada ya kusukuma tawi, endesha ssh deploy@preview.example.com up <branch> na uweke URL iliyochapishwa kwenye muhtasari wako. Endesha down tawi likiunganishwa au likiachwa.

Ikiwa CI yako tayari huendeshwa kila push, ita amri hiyo hiyo kutoka huko na uweke ufunguo mbali kabisa na mazingira ya wakala. Hilo ni chaguo kali zaidi, na tungelichagua kwa chochote kinachozidi mradi binafsi.

Mambo ya kufuatilia

  • Diski. Kila ujenzi huacha tabaka za picha. Cron ya kila wiki yenye docker image prune -f huidhibiti; down tayari hufuta picha ya onyesho lenyewe.
  • Matawi ambayo hakuna anayeyafunga. Mawakala hufungua matawi mengi kuliko watu. Kazi ya cron inayoorodhesha kontena za preview-* zilizo na zaidi ya wiki moja na kuendesha preview-down juu yake inakuepusha kukuta maonyesho ishirini yaliyosahauliwa.
  • Siri. Maonyesho ya awali yanapaswa kuendeshwa kwa vitambulisho vya majaribio. Nenosiri la basic auth huwazuia wageni, lakini haifanyi iwe sawa kuunganisha onyesho na hifadhidata ya uzalishaji.
  • Muda wa ujenzi. Picha hujengwa kwenye seva, kwa hiyo ujenzi mzito hushindana kwa CPU na maonyesho yanayoendeshwa. Ujenzi ukichukua dakika, jenga kwenye CI na uvute picha.

Wakala mwenyewe hahitaji kuishi kwenye seva hii. Akiishi, ona VPS kwa Claude Code, na ili aagize na kuitunza seva hiyo mwenyewe, muunganishe na seva ya MCP ya EQVPS. Mashine hiyo hiyo pia inaweza kupangisha lango la MCP la timu yako. Kwa kuendesha msimbo usioaminika bila seva yoyote kuna sandbox, na mipango yenye IPv4 yake huanzia $8 kwa mwezi.

Maswali

Kwa nini tusimwache wakala asambaze moja kwa moja kwenye uzalishaji?

Kwa sababu "majaribio yanapita" na "inafanya kazi" si kitu kimoja, na wakala anapaswa kuwa wa mwisho kuamua hilo. Onyesho la awali humpa mtu kitu cha kubofya kabla chochote hakijawafikia watumiaji, kwa gharama ya amri moja ya ziada.

Mpango gani unafaa?

Inategemea maonyesho mangapi yanaendeshwa kwa wakati mmoja. AI-Agent-IP ($15/mwezi, 4 vCPU, 4 GB RAM, diski 40 GB) hubeba kwa urahisi programu kadhaa ndogo za wavuti zenye kikomo cha 512 MB kila moja. Sehemu nzito zaidi ni ujenzi wa Docker, kwa hiyo fuatilia diski na kumbukumbu ikiwa picha zako ni kubwa.

Je, ninahitaji cheti cha wildcard?

Hapana. Caddy hupata yenyewe cheti tofauti kwa kila kikoa kidogo cha onyesho la awali. Rekodi ya DNS tu ndiyo wildcard. Let's Encrypt huruhusu takribani vyeti vipya 50 kwa kila kikoa kilichosajiliwa kwa wiki, vinatosha isipokuwa wakala aunde mamia ya matawi.

Je, wakala anaweza kuharibu seva kwa ufunguo wake wa SSH?

Si kwa ufunguo huo. Umezuiliwa kwa amri moja inayokubali tu "up <tawi>" au "down <tawi>" pamoja na jina salama la tawi. Ufikiaji wa shell, hoja za ziada na usambazaji wa milango hukataliwa.

Je, inafanya kazi kwenye mpango wa NAT?

Hapana. Maonyesho ya awali lazima yafikike kwenye milango 80 na 443 kwenye vikoa vidogo vyake, jambo linalohitaji IPv4 ya umma. Mipango ya NAT hupeleka mlango wa SSH tu.

Maoni

Bado hakuna maoni. Kuwa wa kwanza.

Acha maoni

Maoni yanakaguliwa kabla ya kuonekana.