Initial commit
This commit is contained in:
31
deploy/README.md
Normal file
31
deploy/README.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# Deployment Notes
|
||||
|
||||
Default NAS target:
|
||||
|
||||
```text
|
||||
host: comtropy.synology.me
|
||||
port: 50022
|
||||
remote dir: /volume1/docker/telegram-codex-bot
|
||||
```
|
||||
|
||||
PowerShell deployment:
|
||||
|
||||
```powershell
|
||||
.\deploy\make-env.ps1
|
||||
.\deploy\deploy.ps1 -NasUser your-nas-admin-user
|
||||
```
|
||||
|
||||
The script uploads files over legacy SCP, then runs:
|
||||
|
||||
```bash
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
If the first Codex command fails inside Telegram, open an SSH session and run:
|
||||
|
||||
```bash
|
||||
cd /volume1/docker/telegram-codex-bot
|
||||
docker compose exec telegram-codex-bot codex login --device-auth
|
||||
```
|
||||
|
||||
The `codex-home` directory is mounted to `/root/.codex` so login state persists.
|
||||
24
deploy/check-status.ps1
Normal file
24
deploy/check-status.ps1
Normal file
@@ -0,0 +1,24 @@
|
||||
param(
|
||||
[string]$NasUser = "y2keui",
|
||||
[string]$NasHost = "comtropy.synology.me",
|
||||
[int]$NasPort = 50022,
|
||||
[string]$RemoteDir = "/volume1/docker/telegram-codex-bot",
|
||||
[string]$SshKeyPath = "$env:USERPROFILE\.ssh\nas_codex_ed25519"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$remote = "${NasUser}@${NasHost}"
|
||||
$sshAuthArgs = @()
|
||||
if ($SshKeyPath -and (Test-Path $SshKeyPath)) {
|
||||
$sshAuthArgs = @("-i", $SshKeyPath, "-o", "IdentitiesOnly=yes")
|
||||
}
|
||||
$remoteCommand = @"
|
||||
export PATH=/usr/local/bin:/var/packages/ContainerManager/target/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin
|
||||
cd '$RemoteDir'
|
||||
sudo /usr/local/bin/docker-compose ps
|
||||
echo '--- logs ---'
|
||||
sudo /usr/local/bin/docker-compose logs --tail=160 telegram-codex-bot
|
||||
"@
|
||||
|
||||
ssh @sshAuthArgs -tt -p $NasPort $remote $remoteCommand
|
||||
69
deploy/deploy.ps1
Normal file
69
deploy/deploy.ps1
Normal file
@@ -0,0 +1,69 @@
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$NasUser,
|
||||
|
||||
[string]$NasHost = "comtropy.synology.me",
|
||||
[int]$NasPort = 50022,
|
||||
[string]$RemoteDir = "/volume1/docker/telegram-codex-bot",
|
||||
[string]$SshKeyPath = "$env:USERPROFILE\.ssh\nas_codex_ed25519"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$root = Split-Path -Parent (Split-Path -Parent $MyInvocation.MyCommand.Path)
|
||||
$remote = "${NasUser}@${NasHost}"
|
||||
$remotePath = "/usr/local/bin:/var/packages/ContainerManager/target/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin"
|
||||
$sshAuthArgs = @()
|
||||
if ($SshKeyPath -and (Test-Path $SshKeyPath)) {
|
||||
$sshAuthArgs = @("-i", $SshKeyPath, "-o", "IdentitiesOnly=yes")
|
||||
}
|
||||
|
||||
if (-not (Test-Path (Join-Path $root ".env"))) {
|
||||
Write-Host "Missing .env. Copy .env.example to .env and fill secrets first." -ForegroundColor Yellow
|
||||
exit 1
|
||||
}
|
||||
|
||||
function Invoke-Checked {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[scriptblock]$Script,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$Description
|
||||
)
|
||||
|
||||
& $Script
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "$Description failed with exit code $LASTEXITCODE"
|
||||
}
|
||||
}
|
||||
|
||||
Invoke-Checked -Description "Creating remote directory" -Script {
|
||||
ssh @sshAuthArgs -p $NasPort $remote "export PATH='$remotePath'; mkdir -p '$RemoteDir'"
|
||||
}
|
||||
|
||||
Invoke-Checked -Description "Cleaning old uploaded source files" -Script {
|
||||
ssh @sshAuthArgs -p $NasPort $remote "export PATH='$remotePath'; rm -rf '$RemoteDir/app' '$RemoteDir/scripts'"
|
||||
}
|
||||
|
||||
$uploadPaths = @(
|
||||
(Join-Path $root "app"),
|
||||
(Join-Path $root "scripts"),
|
||||
(Join-Path $root ".dockerignore"),
|
||||
(Join-Path $root ".env"),
|
||||
(Join-Path $root "Dockerfile"),
|
||||
(Join-Path $root "README.md"),
|
||||
(Join-Path $root "docker-compose.yml"),
|
||||
(Join-Path $root "requirements.txt")
|
||||
)
|
||||
|
||||
Invoke-Checked -Description "Uploading project files" -Script {
|
||||
$scpArgs = @("-O") + $sshAuthArgs + @("-P", "$NasPort", "-r") + $uploadPaths + @("${remote}:$RemoteDir/")
|
||||
& scp @scpArgs
|
||||
}
|
||||
|
||||
Invoke-Checked -Description "Building and starting container" -Script {
|
||||
ssh @sshAuthArgs -tt -p $NasPort $remote "export PATH='$remotePath'; cd '$RemoteDir' && mkdir -p data workspaces codex-home && (sudo /usr/local/bin/docker-compose up -d --build || sudo /var/packages/ContainerManager/target/usr/bin/docker-compose up -d --build || sudo docker compose up -d --build)"
|
||||
}
|
||||
|
||||
Write-Host "Deployment finished: $RemoteDir"
|
||||
36
deploy/make-env.ps1
Normal file
36
deploy/make-env.ps1
Normal file
@@ -0,0 +1,36 @@
|
||||
param(
|
||||
[string]$WorkspaceRoot = "/workspaces",
|
||||
[string]$StatePath = "/app/data/state.json"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$root = Split-Path -Parent (Split-Path -Parent $MyInvocation.MyCommand.Path)
|
||||
$envPath = Join-Path $root ".env"
|
||||
|
||||
$secureToken = Read-Host "Telegram bot token" -AsSecureString
|
||||
$tokenPtr = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($secureToken)
|
||||
try {
|
||||
$token = [Runtime.InteropServices.Marshal]::PtrToStringBSTR($tokenPtr)
|
||||
}
|
||||
finally {
|
||||
if ($tokenPtr -ne [IntPtr]::Zero) {
|
||||
[Runtime.InteropServices.Marshal]::ZeroFreeBSTR($tokenPtr)
|
||||
}
|
||||
}
|
||||
$allowedIds = Read-Host "Allowed Telegram user ids (comma-separated; leave blank for /whoami only)"
|
||||
|
||||
@"
|
||||
TELEGRAM_BOT_TOKEN=$token
|
||||
ALLOWED_TELEGRAM_USER_IDS=$allowedIds
|
||||
BOT_STATE_PATH=$StatePath
|
||||
BOT_WORKSPACE_ROOT=$WorkspaceRoot
|
||||
CODEX_BIN=codex
|
||||
CODEX_TIMEOUT_SECONDS=1800
|
||||
CODEX_READONLY_SANDBOX=read-only
|
||||
CODEX_WRITE_SANDBOX=workspace-write
|
||||
CODEX_RESUME_JSON_FLAG_STYLE=before_resume
|
||||
ALLOW_PLAIN_TEXT=true
|
||||
"@ | Set-Content -Path $envPath -Encoding UTF8
|
||||
|
||||
Write-Host "Wrote $envPath"
|
||||
31
deploy/register-ssh-key.ps1
Normal file
31
deploy/register-ssh-key.ps1
Normal file
@@ -0,0 +1,31 @@
|
||||
param(
|
||||
[string]$NasUser = "y2keui",
|
||||
[string]$NasHost = "comtropy.synology.me",
|
||||
[int]$NasPort = 50022,
|
||||
[string]$SshKeyPath = "$env:USERPROFILE\.ssh\nas_codex_ed25519"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
$publicKeyPath = "$SshKeyPath.pub"
|
||||
if (-not (Test-Path $publicKeyPath)) {
|
||||
Write-Host "Missing public key: $publicKeyPath" -ForegroundColor Yellow
|
||||
exit 1
|
||||
}
|
||||
|
||||
$remote = "${NasUser}@${NasHost}"
|
||||
$remoteCommand = @'
|
||||
export PATH=/usr/local/bin:/var/packages/ContainerManager/target/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin
|
||||
umask 077
|
||||
mkdir -p ~/.ssh
|
||||
cat >> ~/.ssh/authorized_keys
|
||||
chmod 700 ~/.ssh
|
||||
chmod 600 ~/.ssh/authorized_keys
|
||||
'@
|
||||
|
||||
Get-Content -Raw $publicKeyPath | ssh -p $NasPort $remote $remoteCommand
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "Registering SSH public key failed with exit code $LASTEXITCODE"
|
||||
}
|
||||
|
||||
Write-Host "Public key registered: $publicKeyPath"
|
||||
Reference in New Issue
Block a user