[{"data":1,"prerenderedAt":1175},["ShallowReactive",2],{"navigation":3,"\u002Finstallation\u002Fserver":194,"\u002Finstallation\u002Fserver-surround":1170},[4,18,31,64,81,102,111,132,149],{"title":5,"path":6,"stem":7,"children":8,"page":17},"Getting started","\u002Fgetting-started","1.getting-started",[9,13],{"title":10,"path":11,"stem":12},"Introduction","\u002Fgetting-started\u002Fintroduction","1.getting-started\u002F1.introduction",{"title":14,"path":15,"stem":16},"Run your first workflow","\u002Fgetting-started\u002Fquickstart","1.getting-started\u002F2.quickstart",false,{"title":19,"path":20,"stem":21,"children":22,"page":17},"Core concepts","\u002Fconcepts","2.concepts",[23,27],{"title":24,"path":25,"stem":26},"The platform model","\u002Fconcepts\u002Fplatform","2.concepts\u002F1.platform",{"title":28,"path":29,"stem":30},"Architecture and boundaries","\u002Fconcepts\u002Farchitecture","2.concepts\u002F2.architecture",{"title":32,"path":33,"stem":34,"children":35,"page":17},"Installation","\u002Finstallation","3.installation",[36,40,44,48,52,56,60],{"title":37,"path":38,"stem":39},"Overview and requirements","\u002Finstallation\u002Foverview","3.installation\u002F1.overview",{"title":41,"path":42,"stem":43},"Local evaluation","\u002Finstallation\u002Flocal-evaluation","3.installation\u002F2.local-evaluation",{"title":45,"path":46,"stem":47},"Install the server","\u002Finstallation\u002Fserver","3.installation\u002F3.server",{"title":49,"path":50,"stem":51},"Install a runner","\u002Finstallation\u002Frunner","3.installation\u002F4.runner",{"title":53,"path":54,"stem":55},"Verify the installation","\u002Finstallation\u002Fverification","3.installation\u002F5.verification",{"title":57,"path":58,"stem":59},"Upgrade the platform","\u002Finstallation\u002Fupgrades","3.installation\u002F6.upgrades",{"title":61,"path":62,"stem":63},"Guided installer","\u002Finstallation\u002Finstaller","3.installation\u002F7.installer",{"title":65,"path":66,"stem":67,"children":68,"page":17},"Build workflows","\u002Fworkflows","4.workflows",[69,73,77],{"title":70,"path":71,"stem":72},"Build a Definition","\u002Fworkflows\u002Fdefinitions","4.workflows\u002F0.definitions",{"title":74,"path":75,"stem":76},"Deploy and run workflows","\u002Fworkflows\u002Fruns","4.workflows\u002F1.runs",{"title":78,"path":79,"stem":80},"Inputs, context, and secrets","\u002Fworkflows\u002Finputs-and-secrets","4.workflows\u002F2.inputs-and-secrets",{"title":82,"path":83,"stem":84,"children":85,"page":17},"Run and recover","\u002Foperations","5.operations",[86,90,94,98],{"title":87,"path":88,"stem":89},"Monitor Runs","\u002Foperations\u002Fmonitoring","5.operations\u002F1.monitoring",{"title":91,"path":92,"stem":93},"Approve prepared steps","\u002Foperations\u002Fapprovals","5.operations\u002F2.approvals",{"title":95,"path":96,"stem":97},"Recover or cancel execution","\u002Foperations\u002Frecovery","5.operations\u002F3.recovery",{"title":99,"path":100,"stem":101},"Troubleshooting","\u002Foperations\u002Ftroubleshooting","5.operations\u002F4.troubleshooting",{"title":103,"path":104,"stem":105,"children":106,"page":17},"Action catalog","\u002Fcatalog","6.catalog",[107],{"title":108,"path":109,"stem":110},"Find and use Actions","\u002Fcatalog\u002Foverview","6.catalog\u002F1.overview",{"title":112,"path":113,"stem":114,"children":115,"page":17},"Administration","\u002Fadministration","7.administration",[116,120,124,128],{"title":117,"path":118,"stem":119},"Registries and Environments","\u002Fadministration\u002Fenvironments","7.administration\u002F2.environments",{"title":121,"path":122,"stem":123},"Manage runners","\u002Fadministration\u002Frunners","7.administration\u002F3.runners",{"title":125,"path":126,"stem":127},"Access and approval policies","\u002Fadministration\u002Faccess","7.administration\u002F4.access",{"title":129,"path":130,"stem":131},"Backups and upgrades","\u002Fadministration\u002Fmaintenance","7.administration\u002F5.maintenance",{"title":133,"path":134,"stem":135,"children":136,"page":17},"Develop Actions","\u002Factions","8.actions",[137,141,145],{"title":138,"path":139,"stem":140},"Build your first Action","\u002Factions\u002Fquickstart","8.actions\u002F1.quickstart",{"title":142,"path":143,"stem":144},"Local development","\u002Factions\u002Flocal-development","8.actions\u002F2.local-development",{"title":146,"path":147,"stem":148},"Publish an Action","\u002Factions\u002Fpublishing","8.actions\u002F3.publishing",{"title":150,"path":151,"stem":152,"children":153,"page":17},"Reference","\u002Freference","9.reference",[154,158,162,166,170,174,178,182,186,190],{"title":155,"path":156,"stem":157},"Operator CLI","\u002Freference\u002Foperator-cli","9.reference\u002F1.operator-cli",{"title":159,"path":160,"stem":161},"Installer CLI","\u002Freference\u002Finstaller-cli","9.reference\u002F10.installer-cli",{"title":163,"path":164,"stem":165},"Definition syntax","\u002Freference\u002Fdefinition","9.reference\u002F2.definition",{"title":167,"path":168,"stem":169},"CLI configuration","\u002Freference\u002Fconfiguration","9.reference\u002F3.configuration",{"title":171,"path":172,"stem":173},"API integration","\u002Freference\u002Fapi","9.reference\u002F4.api",{"title":175,"path":176,"stem":177},"Action CLI","\u002Freference\u002Faction-cli","9.reference\u002F5.action-cli",{"title":179,"path":180,"stem":181},"Action SDK","\u002Freference\u002Fsdk","9.reference\u002F6.sdk",{"title":183,"path":184,"stem":185},"Contracts and compatibility","\u002Freference\u002Fcontracts","9.reference\u002F7.contracts",{"title":187,"path":188,"stem":189},"Server configuration","\u002Freference\u002Fserver-configuration","9.reference\u002F8.server-configuration",{"title":191,"path":192,"stem":193},"Runner configuration","\u002Freference\u002Frunner-configuration","9.reference\u002F9.runner-configuration",{"id":195,"title":45,"body":196,"description":1165,"extension":1166,"meta":1167,"navigation":894,"path":46,"seo":1168,"stem":47,"__hash__":1169},"docs\u002F3.installation\u002F3.server.md",{"type":197,"value":198,"toc":1160},"minimark",[199,222,241,246,253,264,300,303,580,588,591,656,667,682,686,709,758,765,768,798,801,834,840,1057,1082,1092,1096,1099,1134,1145,1148,1156],[200,201,202,203,207,208,212,213,217,218,221],"p",{},"Complete the ",[204,205,206],"a",{"href":38},"requirements and version selection"," first. Choose ",[209,210,211],"strong",{},"one"," deployment method below. Both start a single server with persistent storage, HTTPS on port ",[214,215,216],"code",{},"8080",", and embedded NATS TLS on port ",[214,219,220],{},"4222",".",[200,223,224,225,228,229,232,233,236,237,240],{},"Replace ",[214,226,227],{},"pyplines.example.com"," with your actual server DNS name throughout. Provision a certificate covering that name, its private key, and the public CA certificate. The examples assume these files are available as ",[214,230,231],{},"tls\u002Fserver.crt",", ",[214,234,235],{},"tls\u002Fserver.key",", and ",[214,238,239],{},"tls\u002Fca.crt"," in your installation directory.",[242,243,245],"h2",{"id":244},"option-a-docker-compose","Option A: Docker Compose",[200,247,248,249,252],{},"For guided setup of this deployment, see ",[204,250,251],{"href":62},"the installer",".\nThe instructions below describe manual provisioning.",[200,254,255,256,259,260,263],{},"On the server host, create a private installation directory, enter it, and place your provisioned TLS files in ",[214,257,258],{},"tls\u002F",". Create ",[214,261,262],{},".env"," using the plain platform version selected in the overview:",[265,266,272],"pre",{"className":267,"code":268,"filename":269,"language":270,"meta":271,"style":271},"language-sh shiki shiki-themes pyplines-light pyplines-light pyplines-dark","mkdir -p pyplines-server\u002Ftls\nchmod 700 pyplines-server pyplines-server\u002Ftls\ncd pyplines-server\nprintf 'PLATFORM_VERSION=%s\\n' \"$PLATFORM_VERSION\" > .env\n","Terminal","sh","",[214,273,274,282,288,294],{"__ignoreMap":271},[275,276,279],"span",{"class":277,"line":278},"line",1,[275,280,281],{},"mkdir -p pyplines-server\u002Ftls\n",[275,283,285],{"class":277,"line":284},2,[275,286,287],{},"chmod 700 pyplines-server pyplines-server\u002Ftls\n",[275,289,291],{"class":277,"line":290},3,[275,292,293],{},"cd pyplines-server\n",[275,295,297],{"class":277,"line":296},4,[275,298,299],{},"printf 'PLATFORM_VERSION=%s\\n' \"$PLATFORM_VERSION\" > .env\n",[200,301,302],{},"The following complete Compose file runs only the server. It does not mount the Docker socket or start a runner:",[304,305,308],"code-example",{":line-numbers":306,"caption":307},"true","The server keeps its state in server-data and reads TLS files from a read-only mount.",[265,309,318],{"className":310,"code":311,"filename":312,"highlights":313,"language":317,"meta":271,"style":271},"language-yaml shiki shiki-themes pyplines-light pyplines-light pyplines-dark","name: pyplines-server\nservices:\n  server:\n    image: ghcr.io\u002Fpyplines\u002Fpyplines-server:${PLATFORM_VERSION:?Set PLATFORM_VERSION in .env}\n    command:\n      - start\n      - --data\n      - \u002Fdata\n      - --listen\n      - :8080\n      - --tls-cert\n      - \u002Fcerts\u002Fserver.crt\n      - --tls-key\n      - \u002Fcerts\u002Fserver.key\n      - --nats-listen\n      - :4222\n      - --nats-url\n      - tls:\u002F\u002Fpyplines.example.com:4222\n    ports:\n      - \"8080:8080\"\n      - \"4222:4222\"\n    volumes:\n      - server-data:\u002Fdata\n      - .\u002Ftls:\u002Fcerts:ro\n    restart: on-failure\n    stop_grace_period: 60s\nvolumes:\n  server-data:\n    name: pyplines-server-data\n","compose.yaml",[314,315,316],22,23,24,"yaml",[214,319,320,334,342,349,359,367,376,384,392,400,408,416,424,432,440,448,456,464,472,480,494,506,515,523,531,542,553,561,569],{"__ignoreMap":271},[275,321,322,326,330],{"class":277,"line":278},[275,323,325],{"class":324},"smnRP","name",[275,327,329],{"class":328},"sgMYo",":",[275,331,333],{"class":332},"sfDcV"," pyplines-server\n",[275,335,336,339],{"class":277,"line":284},[275,337,338],{"class":324},"services",[275,340,341],{"class":328},":\n",[275,343,344,347],{"class":277,"line":290},[275,345,346],{"class":324},"  server",[275,348,341],{"class":328},[275,350,351,354,356],{"class":277,"line":296},[275,352,353],{"class":324},"    image",[275,355,329],{"class":328},[275,357,358],{"class":332}," ghcr.io\u002Fpyplines\u002Fpyplines-server:${PLATFORM_VERSION:?Set PLATFORM_VERSION in .env}\n",[275,360,362,365],{"class":277,"line":361},5,[275,363,364],{"class":324},"    command",[275,366,341],{"class":328},[275,368,370,373],{"class":277,"line":369},6,[275,371,372],{"class":328},"      -",[275,374,375],{"class":332}," start\n",[275,377,379,381],{"class":277,"line":378},7,[275,380,372],{"class":328},[275,382,383],{"class":332}," --data\n",[275,385,387,389],{"class":277,"line":386},8,[275,388,372],{"class":328},[275,390,391],{"class":332}," \u002Fdata\n",[275,393,395,397],{"class":277,"line":394},9,[275,396,372],{"class":328},[275,398,399],{"class":332}," --listen\n",[275,401,403,405],{"class":277,"line":402},10,[275,404,372],{"class":328},[275,406,407],{"class":332}," :8080\n",[275,409,411,413],{"class":277,"line":410},11,[275,412,372],{"class":328},[275,414,415],{"class":332}," --tls-cert\n",[275,417,419,421],{"class":277,"line":418},12,[275,420,372],{"class":328},[275,422,423],{"class":332}," \u002Fcerts\u002Fserver.crt\n",[275,425,427,429],{"class":277,"line":426},13,[275,428,372],{"class":328},[275,430,431],{"class":332}," --tls-key\n",[275,433,435,437],{"class":277,"line":434},14,[275,436,372],{"class":328},[275,438,439],{"class":332}," \u002Fcerts\u002Fserver.key\n",[275,441,443,445],{"class":277,"line":442},15,[275,444,372],{"class":328},[275,446,447],{"class":332}," --nats-listen\n",[275,449,451,453],{"class":277,"line":450},16,[275,452,372],{"class":328},[275,454,455],{"class":332}," :4222\n",[275,457,459,461],{"class":277,"line":458},17,[275,460,372],{"class":328},[275,462,463],{"class":332}," --nats-url\n",[275,465,467,469],{"class":277,"line":466},18,[275,468,372],{"class":328},[275,470,471],{"class":332}," tls:\u002F\u002Fpyplines.example.com:4222\n",[275,473,475,478],{"class":277,"line":474},19,[275,476,477],{"class":324},"    ports",[275,479,341],{"class":328},[275,481,483,485,488,491],{"class":277,"line":482},20,[275,484,372],{"class":328},[275,486,487],{"class":328}," \"",[275,489,490],{"class":332},"8080:8080",[275,492,493],{"class":328},"\"\n",[275,495,497,499,501,504],{"class":277,"line":496},21,[275,498,372],{"class":328},[275,500,487],{"class":328},[275,502,503],{"class":332},"4222:4222",[275,505,493],{"class":328},[275,507,510,513],{"class":508,"line":314},[277,509],"highlight",[275,511,512],{"class":324},"    volumes",[275,514,341],{"class":328},[275,516,518,520],{"class":517,"line":315},[277,509],[275,519,372],{"class":328},[275,521,522],{"class":332}," server-data:\u002Fdata\n",[275,524,526,528],{"class":525,"line":316},[277,509],[275,527,372],{"class":328},[275,529,530],{"class":332}," .\u002Ftls:\u002Fcerts:ro\n",[275,532,534,537,539],{"class":277,"line":533},25,[275,535,536],{"class":324},"    restart",[275,538,329],{"class":328},[275,540,541],{"class":332}," on-failure\n",[275,543,545,548,550],{"class":277,"line":544},26,[275,546,547],{"class":324},"    stop_grace_period",[275,549,329],{"class":328},[275,551,552],{"class":332}," 60s\n",[275,554,556,559],{"class":277,"line":555},27,[275,557,558],{"class":324},"volumes",[275,560,341],{"class":328},[275,562,564,567],{"class":277,"line":563},28,[275,565,566],{"class":324},"  server-data",[275,568,341],{"class":328},[275,570,572,575,577],{"class":277,"line":571},29,[275,573,574],{"class":324},"    name",[275,576,329],{"class":328},[275,578,579],{"class":332}," pyplines-server-data\n",[200,581,582,583,587],{},"These port mappings listen on the host's interfaces. Restrict access through your host\u002Fnetwork firewall as described in ",[204,584,586],{"href":585},"\u002Finstallation\u002Foverview#network-and-tls-plan","the network plan",". Bind to a specific host address if your network layout requires it.",[200,589,590],{},"Create a bootstrap password file with at least 12 characters. This example generates one without placing the password in command arguments:",[265,592,594],{"className":267,"code":593,"filename":269,"language":270,"meta":271,"style":271},"umask 077\nopenssl rand -base64 24 > bootstrap-password\ntest -s tls\u002Fserver.crt && test -s tls\u002Fserver.key\ndocker compose config --quiet\ndocker compose pull server\ndocker compose run --rm --no-deps \\\n  -v \"$PWD\u002Fbootstrap-password:\u002Frun\u002Fsecrets\u002Fbootstrap-password:ro\" \\\n  server bootstrap --data \u002Fdata --username admin \\\n  --password-file \u002Frun\u002Fsecrets\u002Fbootstrap-password\ndocker compose up -d server\ndocker compose ps\ndocker compose logs --tail 100 server\n",[214,595,596,601,606,611,616,621,626,631,636,641,646,651],{"__ignoreMap":271},[275,597,598],{"class":277,"line":278},[275,599,600],{},"umask 077\n",[275,602,603],{"class":277,"line":284},[275,604,605],{},"openssl rand -base64 24 > bootstrap-password\n",[275,607,608],{"class":277,"line":290},[275,609,610],{},"test -s tls\u002Fserver.crt && test -s tls\u002Fserver.key\n",[275,612,613],{"class":277,"line":296},[275,614,615],{},"docker compose config --quiet\n",[275,617,618],{"class":277,"line":361},[275,619,620],{},"docker compose pull server\n",[275,622,623],{"class":277,"line":369},[275,624,625],{},"docker compose run --rm --no-deps \\\n",[275,627,628],{"class":277,"line":378},[275,629,630],{},"  -v \"$PWD\u002Fbootstrap-password:\u002Frun\u002Fsecrets\u002Fbootstrap-password:ro\" \\\n",[275,632,633],{"class":277,"line":386},[275,634,635],{},"  server bootstrap --data \u002Fdata --username admin \\\n",[275,637,638],{"class":277,"line":394},[275,639,640],{},"  --password-file \u002Frun\u002Fsecrets\u002Fbootstrap-password\n",[275,642,643],{"class":277,"line":402},[275,644,645],{},"docker compose up -d server\n",[275,647,648],{"class":277,"line":410},[275,649,650],{},"docker compose ps\n",[275,652,653],{"class":277,"line":418},[275,654,655],{},"docker compose logs --tail 100 server\n",[200,657,658,659,662,663,666],{},"Bootstrap and the running server use the ",[209,660,661],{},"same"," ",[214,664,665],{},"server-data"," volume. Bootstrap creates the initial administrator only on an uninitialized installation. Do not run another server against that volume. After successful login, retain the password in your credential manager and remove the bootstrap file; the running service does not need it.",[200,668,669,670,673,674,677,678,681],{},"Use ",[214,671,672],{},"docker compose stop server"," during planned maintenance and ",[214,675,676],{},"docker compose start server"," to restart it. The data survives container replacement. Do not use ",[214,679,680],{},"down --volumes"," or prune this volume on an installation you intend to retain.",[242,683,685],{"id":684},"option-b-linux-service","Option B: Linux service",[200,687,688,689,692,693,696,697,700,701,704,705,708],{},"These commands target a Linux systemd host with ",[214,690,691],{},"sudo",", GitHub CLI, and GNU checksum tools. Set ",[214,694,695],{},"PLATFORM_TAG"," and ",[214,698,699],{},"PLATFORM_VERSION"," from the overview, and select ",[214,702,703],{},"amd64"," for x86-64 or ",[214,706,707],{},"arm64"," for AArch64:",[265,710,712],{"className":267,"code":711,"filename":269,"language":270,"meta":271,"style":271},"export ARCH=amd64\nmkdir -p download\u002Fbinaries\ngh release download \"$PLATFORM_TAG\" --repo pyplines\u002Fpyplines \\\n  --pattern \"pyplines-server-linux-$ARCH\" --dir download\u002Fbinaries\ngh release download \"$PLATFORM_TAG\" --repo pyplines\u002Fpyplines \\\n  --pattern SHA256SUMS --dir download\n(cd download && sha256sum --check --ignore-missing SHA256SUMS)\nsudo install -m 0755 \"download\u002Fbinaries\u002Fpyplines-server-linux-$ARCH\" \u002Fusr\u002Flocal\u002Fbin\u002Fpyplines-server\npyplines-server version\n",[214,713,714,719,724,729,734,738,743,748,753],{"__ignoreMap":271},[275,715,716],{"class":277,"line":278},[275,717,718],{},"export ARCH=amd64\n",[275,720,721],{"class":277,"line":284},[275,722,723],{},"mkdir -p download\u002Fbinaries\n",[275,725,726],{"class":277,"line":290},[275,727,728],{},"gh release download \"$PLATFORM_TAG\" --repo pyplines\u002Fpyplines \\\n",[275,730,731],{"class":277,"line":296},[275,732,733],{},"  --pattern \"pyplines-server-linux-$ARCH\" --dir download\u002Fbinaries\n",[275,735,736],{"class":277,"line":361},[275,737,728],{},[275,739,740],{"class":277,"line":369},[275,741,742],{},"  --pattern SHA256SUMS --dir download\n",[275,744,745],{"class":277,"line":378},[275,746,747],{},"(cd download && sha256sum --check --ignore-missing SHA256SUMS)\n",[275,749,750],{"class":277,"line":386},[275,751,752],{},"sudo install -m 0755 \"download\u002Fbinaries\u002Fpyplines-server-linux-$ARCH\" \u002Fusr\u002Flocal\u002Fbin\u002Fpyplines-server\n",[275,754,755],{"class":277,"line":394},[275,756,757],{},"pyplines-server version\n",[200,759,760,761,764],{},"The checksum file uses ",[214,762,763],{},"binaries\u002F"," paths, hence the download layout above. Confirm the reported version matches the selected platform release. Use a new download directory for a different release.",[200,766,767],{},"Create a dedicated account and install your TLS material:",[265,769,771],{"className":267,"code":770,"filename":269,"language":270,"meta":271,"style":271},"sudo useradd --system --home-dir \u002Fvar\u002Flib\u002Fpyplines --shell \u002Fusr\u002Fsbin\u002Fnologin pyplines-server\nsudo install -d -o pyplines-server -g pyplines-server -m 0700 \u002Fvar\u002Flib\u002Fpyplines\nsudo install -d -o root -g pyplines-server -m 0750 \u002Fetc\u002Fpyplines\nsudo install -o root -g pyplines-server -m 0640 tls\u002Fserver.crt \u002Fetc\u002Fpyplines\u002Fserver.crt\nsudo install -o root -g pyplines-server -m 0640 tls\u002Fserver.key \u002Fetc\u002Fpyplines\u002Fserver.key\n",[214,772,773,778,783,788,793],{"__ignoreMap":271},[275,774,775],{"class":277,"line":278},[275,776,777],{},"sudo useradd --system --home-dir \u002Fvar\u002Flib\u002Fpyplines --shell \u002Fusr\u002Fsbin\u002Fnologin pyplines-server\n",[275,779,780],{"class":277,"line":284},[275,781,782],{},"sudo install -d -o pyplines-server -g pyplines-server -m 0700 \u002Fvar\u002Flib\u002Fpyplines\n",[275,784,785],{"class":277,"line":290},[275,786,787],{},"sudo install -d -o root -g pyplines-server -m 0750 \u002Fetc\u002Fpyplines\n",[275,789,790],{"class":277,"line":296},[275,791,792],{},"sudo install -o root -g pyplines-server -m 0640 tls\u002Fserver.crt \u002Fetc\u002Fpyplines\u002Fserver.crt\n",[275,794,795],{"class":277,"line":361},[275,796,797],{},"sudo install -o root -g pyplines-server -m 0640 tls\u002Fserver.key \u002Fetc\u002Fpyplines\u002Fserver.key\n",[200,799,800],{},"Create and provision the administrator password before starting the service:",[265,802,804],{"className":267,"code":803,"filename":269,"language":270,"meta":271,"style":271},"umask 077\nopenssl rand -base64 24 > bootstrap-password\nsudo install -o pyplines-server -g pyplines-server -m 0600 bootstrap-password \u002Fetc\u002Fpyplines\u002Fbootstrap-password\nsudo -u pyplines-server \u002Fusr\u002Flocal\u002Fbin\u002Fpyplines-server bootstrap \\\n  --data \u002Fvar\u002Flib\u002Fpyplines --username admin \\\n  --password-file \u002Fetc\u002Fpyplines\u002Fbootstrap-password\n",[214,805,806,810,814,819,824,829],{"__ignoreMap":271},[275,807,808],{"class":277,"line":278},[275,809,600],{},[275,811,812],{"class":277,"line":284},[275,813,605],{},[275,815,816],{"class":277,"line":290},[275,817,818],{},"sudo install -o pyplines-server -g pyplines-server -m 0600 bootstrap-password \u002Fetc\u002Fpyplines\u002Fbootstrap-password\n",[275,820,821],{"class":277,"line":296},[275,822,823],{},"sudo -u pyplines-server \u002Fusr\u002Flocal\u002Fbin\u002Fpyplines-server bootstrap \\\n",[275,825,826],{"class":277,"line":361},[275,827,828],{},"  --data \u002Fvar\u002Flib\u002Fpyplines --username admin \\\n",[275,830,831],{"class":277,"line":369},[275,832,833],{},"  --password-file \u002Fetc\u002Fpyplines\u002Fbootstrap-password\n",[200,835,836,837,329],{},"Save this unit as ",[214,838,839],{},"\u002Fetc\u002Fsystemd\u002Fsystem\u002Fpyplines-server.service",[265,841,846],{"className":842,"code":843,"filename":844,"language":845,"meta":271,"style":271},"language-ini shiki shiki-themes pyplines-light pyplines-light pyplines-dark","[Unit]\nDescription=Pyplines server\nWants=network-online.target\nAfter=network-online.target\n\n[Service]\nType=simple\nUser=pyplines-server\nGroup=pyplines-server\nStateDirectory=pyplines\nStateDirectoryMode=0700\nUMask=0077\nExecStart=\u002Fusr\u002Flocal\u002Fbin\u002Fpyplines-server start \\\n  --data \u002Fvar\u002Flib\u002Fpyplines \\\n  --listen :8080 \\\n  --tls-cert \u002Fetc\u002Fpyplines\u002Fserver.crt \\\n  --tls-key \u002Fetc\u002Fpyplines\u002Fserver.key \\\n  --nats-listen :4222 \\\n  --nats-url tls:\u002F\u002Fpyplines.example.com:4222\nRestart=on-failure\nRestartSec=5s\nTimeoutStopSec=60s\n\n[Install]\nWantedBy=multi-user.target\n","pyplines-server.service","ini",[214,847,848,859,871,881,890,896,905,915,925,934,944,954,964,974,979,984,989,994,999,1004,1014,1024,1034,1038,1047],{"__ignoreMap":271},[275,849,850,853,856],{"class":277,"line":278},[275,851,852],{"class":328},"[",[275,854,855],{"class":324},"Unit",[275,857,858],{"class":328},"]\n",[275,860,861,865,868],{"class":277,"line":284},[275,862,864],{"class":863},"sYpJS","Description",[275,866,867],{"class":328},"=",[275,869,870],{"class":324},"Pyplines server\n",[275,872,873,876,878],{"class":277,"line":290},[275,874,875],{"class":863},"Wants",[275,877,867],{"class":328},[275,879,880],{"class":324},"network-online.target\n",[275,882,883,886,888],{"class":277,"line":296},[275,884,885],{"class":863},"After",[275,887,867],{"class":328},[275,889,880],{"class":324},[275,891,892],{"class":277,"line":361},[275,893,895],{"emptyLinePlaceholder":894},true,"\n",[275,897,898,900,903],{"class":277,"line":369},[275,899,852],{"class":328},[275,901,902],{"class":324},"Service",[275,904,858],{"class":328},[275,906,907,910,912],{"class":277,"line":378},[275,908,909],{"class":863},"Type",[275,911,867],{"class":328},[275,913,914],{"class":324},"simple\n",[275,916,917,920,922],{"class":277,"line":386},[275,918,919],{"class":863},"User",[275,921,867],{"class":328},[275,923,924],{"class":324},"pyplines-server\n",[275,926,927,930,932],{"class":277,"line":394},[275,928,929],{"class":863},"Group",[275,931,867],{"class":328},[275,933,924],{"class":324},[275,935,936,939,941],{"class":277,"line":402},[275,937,938],{"class":863},"StateDirectory",[275,940,867],{"class":328},[275,942,943],{"class":324},"pyplines\n",[275,945,946,949,951],{"class":277,"line":410},[275,947,948],{"class":863},"StateDirectoryMode",[275,950,867],{"class":328},[275,952,953],{"class":324},"0700\n",[275,955,956,959,961],{"class":277,"line":418},[275,957,958],{"class":863},"UMask",[275,960,867],{"class":328},[275,962,963],{"class":324},"0077\n",[275,965,966,969,971],{"class":277,"line":426},[275,967,968],{"class":863},"ExecStart",[275,970,867],{"class":328},[275,972,973],{"class":324},"\u002Fusr\u002Flocal\u002Fbin\u002Fpyplines-server start \\\n",[275,975,976],{"class":277,"line":434},[275,977,978],{"class":324},"  --data \u002Fvar\u002Flib\u002Fpyplines \\\n",[275,980,981],{"class":277,"line":442},[275,982,983],{"class":324},"  --listen :8080 \\\n",[275,985,986],{"class":277,"line":450},[275,987,988],{"class":324},"  --tls-cert \u002Fetc\u002Fpyplines\u002Fserver.crt \\\n",[275,990,991],{"class":277,"line":458},[275,992,993],{"class":324},"  --tls-key \u002Fetc\u002Fpyplines\u002Fserver.key \\\n",[275,995,996],{"class":277,"line":466},[275,997,998],{"class":324},"  --nats-listen :4222 \\\n",[275,1000,1001],{"class":277,"line":474},[275,1002,1003],{"class":324},"  --nats-url tls:\u002F\u002Fpyplines.example.com:4222\n",[275,1005,1006,1009,1011],{"class":277,"line":482},[275,1007,1008],{"class":863},"Restart",[275,1010,867],{"class":328},[275,1012,1013],{"class":324},"on-failure\n",[275,1015,1016,1019,1021],{"class":277,"line":496},[275,1017,1018],{"class":863},"RestartSec",[275,1020,867],{"class":328},[275,1022,1023],{"class":324},"5s\n",[275,1025,1026,1029,1031],{"class":277,"line":314},[275,1027,1028],{"class":863},"TimeoutStopSec",[275,1030,867],{"class":328},[275,1032,1033],{"class":324},"60s\n",[275,1035,1036],{"class":277,"line":315},[275,1037,895],{"emptyLinePlaceholder":894},[275,1039,1040,1042,1045],{"class":277,"line":316},[275,1041,852],{"class":328},[275,1043,1044],{"class":324},"Install",[275,1046,858],{"class":328},[275,1048,1049,1052,1054],{"class":277,"line":533},[275,1050,1051],{"class":863},"WantedBy",[275,1053,867],{"class":328},[275,1055,1056],{"class":324},"multi-user.target\n",[265,1058,1060],{"className":267,"code":1059,"filename":269,"language":270,"meta":271,"style":271},"sudo systemctl daemon-reload\nsudo systemctl enable --now pyplines-server\nsudo systemctl status pyplines-server\nsudo journalctl -u pyplines-server -n 100 --no-pager\n",[214,1061,1062,1067,1072,1077],{"__ignoreMap":271},[275,1063,1064],{"class":277,"line":278},[275,1065,1066],{},"sudo systemctl daemon-reload\n",[275,1068,1069],{"class":277,"line":284},[275,1070,1071],{},"sudo systemctl enable --now pyplines-server\n",[275,1073,1074],{"class":277,"line":290},[275,1075,1076],{},"sudo systemctl status pyplines-server\n",[275,1078,1079],{"class":277,"line":296},[275,1080,1081],{},"sudo journalctl -u pyplines-server -n 100 --no-pager\n",[200,1083,1084,1085,1088,1089,221],{},"After successful login, store the password in your credential manager and remove both bootstrap password files. Use ",[214,1086,1087],{},"sudo systemctl stop pyplines-server"," for planned maintenance. The service's data remains in ",[214,1090,1091],{},"\u002Fvar\u002Flib\u002Fpyplines",[242,1093,1095],{"id":1094},"check-https-and-log-in","Check HTTPS and log in",[200,1097,1098],{},"From a workstation that can reach the server:",[265,1100,1102],{"className":267,"code":1101,"filename":269,"language":270,"meta":271,"style":271},"curl --fail --cacert .\u002Ftls\u002Fca.crt https:\u002F\u002Fpyplines.example.com:8080\u002Fhealth\npython3 -m venv .venv\nsource .venv\u002Fbin\u002Factivate\npython -m pip install \"pyplines-cli==$TOOLING_VERSION\"\npyplines config set tls.ca_file \"$PWD\u002Ftls\u002Fca.crt\"\npyplines login https:\u002F\u002Fpyplines.example.com:8080 --username admin\n",[214,1103,1104,1109,1114,1119,1124,1129],{"__ignoreMap":271},[275,1105,1106],{"class":277,"line":278},[275,1107,1108],{},"curl --fail --cacert .\u002Ftls\u002Fca.crt https:\u002F\u002Fpyplines.example.com:8080\u002Fhealth\n",[275,1110,1111],{"class":277,"line":284},[275,1112,1113],{},"python3 -m venv .venv\n",[275,1115,1116],{"class":277,"line":290},[275,1117,1118],{},"source .venv\u002Fbin\u002Factivate\n",[275,1120,1121],{"class":277,"line":296},[275,1122,1123],{},"python -m pip install \"pyplines-cli==$TOOLING_VERSION\"\n",[275,1125,1126],{"class":277,"line":361},[275,1127,1128],{},"pyplines config set tls.ca_file \"$PWD\u002Ftls\u002Fca.crt\"\n",[275,1130,1131],{"class":277,"line":369},[275,1132,1133],{},"pyplines login https:\u002F\u002Fpyplines.example.com:8080 --username admin\n",[200,1135,1136,1137,1140,1141,1144],{},"Copy only the public CA certificate to that workstation. Omit ",[214,1138,1139],{},"--cacert"," and the extra CLI CA setting when system trust already covers your certificate. Login prompts for the bootstrap password. ",[214,1142,1143],{},"\u002Fhealth"," confirms that the HTTP service responds; it does not prove that a runner can execute an Action.",[200,1146,1147],{},"If startup fails, check certificate\u002Fkey readability, hostname coverage, the data directory's ownership, and port availability. A lock error means another server process may already own that data directory. The HTTPS service will not start if embedded NATS fails to start.",[200,1149,1150,1151,1153,1154,221],{},"Continue with ",[204,1152,49],{"href":50},". Full flags, environment variables, and persistence details are in ",[204,1155,187],{"href":188},[1157,1158,1159],"style",{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .smnRP, html code.shiki .smnRP{--shiki-light:#243247;--shiki-default:#243247;--shiki-dark:#DCE6F0}html pre.shiki code .sgMYo, html code.shiki .sgMYo{--shiki-light:#54657A;--shiki-default:#54657A;--shiki-dark:#A9B8CA}html pre.shiki code .sfDcV, html code.shiki .sfDcV{--shiki-light:#34694B;--shiki-default:#34694B;--shiki-dark:#9BC9AD}html pre.shiki code .sYpJS, html code.shiki .sYpJS{--shiki-light:#806000;--shiki-default:#806000;--shiki-dark:#F2CD66}",{"title":271,"searchDepth":284,"depth":284,"links":1161},[1162,1163,1164],{"id":244,"depth":284,"text":245},{"id":684,"depth":284,"text":685},{"id":1094,"depth":284,"text":1095},"Deploy a persistent Pyplines server with TLS and its first administrator account.","md",{},{"title":45,"description":1165},"o6m48od5cZewd7gBB60h3VQ9joYNMf8BeHnKNJVOvMM",[1171,1173],{"title":41,"path":42,"stem":43,"description":1172,"children":-1},"Run published server and runner images on one host using the repository's evaluation appliance.",{"title":49,"path":50,"stem":51,"description":1174,"children":-1},"Prepare Docker and persistent work storage, enroll a runner, and verify admission.",1792213696899]