[{"data":1,"prerenderedAt":626},["ShallowReactive",2],{"docs-navigation":3,"docs-\u002Fdocs\u002Fget-started\u002Finstallation":90,"docs-surround-\u002Fdocs\u002Fget-started\u002Finstallation":621},[4],{"title":5,"path":6,"stem":7,"children":8,"page":34},"Docs","\u002Fdocs","docs",[9,35,56,77],{"title":10,"path":11,"stem":12,"children":13,"page":34},"Get Started","\u002Fdocs\u002Fget-started","docs\u002F1.get-started",[14,18,22,26,30],{"title":15,"path":16,"stem":17},"Introduction","\u002Fdocs\u002Fget-started\u002Fintroduction","docs\u002F1.get-started\u002F1.introduction",{"title":19,"path":20,"stem":21},"Concepts","\u002Fdocs\u002Fget-started\u002Fconcepts","docs\u002F1.get-started\u002F2.concepts",{"title":23,"path":24,"stem":25},"Installation","\u002Fdocs\u002Fget-started\u002Finstallation","docs\u002F1.get-started\u002F3.installation",{"title":27,"path":28,"stem":29},"Setup","\u002Fdocs\u002Fget-started\u002Fsetup","docs\u002F1.get-started\u002F4.setup",{"title":31,"path":32,"stem":33},"Maintenance","\u002Fdocs\u002Fget-started\u002Fmaintenance","docs\u002F1.get-started\u002F5.maintenance",false,{"title":36,"path":37,"stem":38,"children":39,"page":34},"Usage","\u002Fdocs\u002Fusage","docs\u002F2.usage",[40,44,48,52],{"title":41,"path":42,"stem":43},"Projects","\u002Fdocs\u002Fusage\u002Fprojects","docs\u002F2.usage\u002F1.projects",{"title":45,"path":46,"stem":47},"Workflows","\u002Fdocs\u002Fusage\u002Fworkflows","docs\u002F2.usage\u002F2.workflows",{"title":49,"path":50,"stem":51},"Triggers","\u002Fdocs\u002Fusage\u002Ftriggers","docs\u002F2.usage\u002F3.triggers",{"title":53,"path":54,"stem":55},"AI Agent","\u002Fdocs\u002Fusage\u002Fagent","docs\u002F2.usage\u002F4.agent",{"title":57,"path":58,"stem":59,"children":60,"page":34},"Integrations","\u002Fdocs\u002Fintegrations","docs\u002F3.integrations",[61,65,69,73],{"title":62,"path":63,"stem":64},"GitHub","\u002Fdocs\u002Fintegrations\u002Fgithub","docs\u002F3.integrations\u002F1.github",{"title":66,"path":67,"stem":68},"Jira","\u002Fdocs\u002Fintegrations\u002Fjira","docs\u002F3.integrations\u002F2.jira",{"title":70,"path":71,"stem":72},"Plane","\u002Fdocs\u002Fintegrations\u002Fplane","docs\u002F3.integrations\u002F3.plane",{"title":74,"path":75,"stem":76},"Linear","\u002Fdocs\u002Fintegrations\u002Flinear","docs\u002F3.integrations\u002F4.linear",{"title":78,"path":79,"stem":80,"children":81,"page":34},"Resources","\u002Fdocs\u002Fresources","docs\u002F4.resources",[82,86],{"title":83,"path":84,"stem":85},"Beta Testers","\u002Fdocs\u002Fresources\u002Fbeta-testers","docs\u002F4.resources\u002F1.beta-testers",{"title":87,"path":88,"stem":89},"Troubleshooting","\u002Fdocs\u002Fresources\u002Ftroubleshooting","docs\u002F4.resources\u002F2.troubleshooting",{"id":91,"title":23,"body":92,"description":615,"extension":616,"meta":617,"navigation":618,"path":24,"seo":619,"stem":25,"__hash__":620},"docs_en\u002Fdocs\u002F1.get-started\u002F3.installation.md",{"type":93,"value":94,"toc":595},"minimark",[95,110,115,120,123,146,152,156,164,167,171,215,218,222,237,241,244,276,287,307,356,359,368,467,471,488,492,495,583,591],[96,97,98,99,106,107,109],"p",{},"Knecht is installed on a server you control. One script sets up Docker, the ",[100,101,105],"a",{"href":102,"rel":103},"https:\u002F\u002Fddev.com",[104],"nofollow","DDEV"," CLI, and the app itself. This page ends when the dashboard is reachable under your domain. What happens on the first visit is covered in ",[100,108,27],{"href":28},".",[111,112,114],"h2",{"id":113},"requirements","Requirements",[116,117,119],"h3",{"id":118},"server","Server",[96,121,122],{},"A fresh server with root access, used only for Knecht. This can be:",[124,125,126,136,139],"ul",{},[127,128,129,130,135],"li",{},"A VPS, for example a ",[100,131,134],{"href":132,"rel":133},"https:\u002F\u002Fwww.hetzner.com\u002Fcloud",[104],"Hetzner"," CX23 or CX33",[127,137,138],{},"A dedicated server or a virtual machine",[127,140,141,142,109],{},"A Mac, for example a Mac mini, through a Lima VM. See ",[100,143,145],{"href":144},"#install-on-macos","Install on macOS",[147,148,149],"note",{},[96,150,151],{},"Keep the host free of other Docker setups. Knecht boots the project environments on the host's Docker daemon and takes ports 80 and 443 for its own entry point.",[116,153,155],{"id":154},"operating-system","Operating System",[124,157,158,161],{},[127,159,160],{},"Ubuntu 24.04",[127,162,163],{},"amd64 or arm64",[96,165,166],{},"The installer stops on other distributions. Other Ubuntu versions are not tested.",[116,168,170],{"id":169},"hardware","Hardware",[172,173,174,189],"table",{},[175,176,177],"thead",{},[178,179,180,183,186],"tr",{},[181,182],"th",{},[181,184,185],{},"Minimum",[181,187,188],{},"Comfortable",[190,191,192,204],"tbody",{},[178,193,194,198,201],{},[195,196,197],"td",{},"RAM",[195,199,200],{},"4 GB",[195,202,203],{},"8 GB",[178,205,206,209,212],{},[195,207,208],{},"Disk",[195,210,211],{},"40 GB",[195,213,214],{},"80 GB",[96,216,217],{},"Every running preview costs one web and one database container. More parallel previews need more RAM.",[116,219,221],{"id":220},"domain-and-network","Domain and Network",[124,223,224,231,234],{},[127,225,226,227],{},"A domain or subdomain for the instance, for example ",[228,229,230],"code",{},"knecht.example.com",[127,232,233],{},"Access to its DNS, for two records you set after the install",[127,235,236],{},"Ports 80 and 443 reachable from the internet",[111,238,240],{"id":239},"install-on-linux","Install on Linux",[96,242,243],{},"As root on the fresh server:",[245,246,251],"pre",{"className":247,"code":248,"language":249,"meta":250,"style":250},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","curl -fsSL https:\u002F\u002Fraw.githubusercontent.com\u002Fknecht-works\u002Fknecht-cloud\u002Fmain\u002Fscripts\u002Finstall.sh | bash\n","bash","",[228,252,253],{"__ignoreMap":250},[254,255,258,262,266,269,273],"span",{"class":256,"line":257},"line",1,[254,259,261],{"class":260},"sBMFI","curl",[254,263,265],{"class":264},"sfazB"," -fsSL",[254,267,268],{"class":264}," https:\u002F\u002Fraw.githubusercontent.com\u002Fknecht-works\u002Fknecht-cloud\u002Fmain\u002Fscripts\u002Finstall.sh",[254,270,272],{"class":271},"sMK4o"," |",[254,274,275],{"class":260}," bash\n",[96,277,278,279,282,283,286],{},"The installer asks for your domain and does the rest. It installs Docker and the pinned DDEV CLI, warms up the DDEV images, checks out the latest release under ",[228,280,281],{},"\u002Fopt\u002Fknecht",", writes a ",[228,284,285],{},".env",", and starts the app together with the Caddy TLS entry point via Docker Compose. It takes a few minutes and is safe to re-run if something breaks halfway.",[147,288,289],{},[96,290,291,292,295,296,299,300,303,304,306],{},"For a non-interactive install, pass the domain up front with ",[228,293,294],{},"KNECHT_DOMAIN=knecht.example.com bash",". Any further ",[228,297,298],{},"KNECHT_*"," variable, for example ",[228,301,302],{},"KNECHT_AI_KEY",", is carried into the ",[228,305,285],{}," and locks that setting in the dashboard.",[308,309,311,315,322,330,336,340,343,347],"steps",{"level":310},"3",[116,312,314],{"id":313},"set-the-dns-records","Set the DNS Records",[96,316,317,318,321],{},"Two ",[228,319,320],{},"A"," records, both pointing at the server's IP:",[245,323,328],{"className":324,"code":326,"language":327},[325],"language-text","knecht.example.com\n*.preview.knecht.example.com\n","text",[228,329,326],{"__ignoreMap":250},[96,331,332,333,109],{},"The wildcard serves the preview URLs. Every session gets its own hostname below ",[228,334,335],{},"preview",[116,337,339],{"id":338},"open-ports-80-and-443","Open Ports 80 and 443",[96,341,342],{},"Both must be reachable from the internet. On a cloud VPS this usually means a rule in the provider's firewall.",[116,344,346],{"id":345},"open-the-dashboard","Open the Dashboard",[96,348,349,350,353,354,109],{},"Visit ",[228,351,352],{},"https:\u002F\u002Fknecht.example.com",". Caddy fetches the certificate on first start, so the first request can take a moment. The page that opens is the GitHub App setup, continued in ",[100,355,27],{"href":28},[111,357,145],{"id":358},"install-on-macos",[96,360,361,362,367],{},"The run substrate, host Docker plus DDEV, is Linux only. On a Mac the same setup runs inside a ",[100,363,366],{"href":364,"rel":365},"https:\u002F\u002Flima-vm.io",[104],"Lima"," VM. The template from the repo gives the VM 4 CPUs, 8 GB RAM, and 80 GB disk, and forwards ports 80 and 443 on all interfaces of the Mac.",[308,369,370,374,416,420,449,452,456,459],{"level":310},[116,371,373],{"id":372},"create-the-vm","Create the VM",[245,375,377],{"className":247,"code":376,"language":249,"meta":250,"style":250},"brew install lima\nlimactl create --name=knecht https:\u002F\u002Fraw.githubusercontent.com\u002Fknecht-works\u002Fknecht-cloud\u002Fmain\u002Fscripts\u002Flima-server.yaml\nlimactl start knecht\n",[228,378,379,390,405],{"__ignoreMap":250},[254,380,381,384,387],{"class":256,"line":257},[254,382,383],{"class":260},"brew",[254,385,386],{"class":264}," install",[254,388,389],{"class":264}," lima\n",[254,391,393,396,399,402],{"class":256,"line":392},2,[254,394,395],{"class":260},"limactl",[254,397,398],{"class":264}," create",[254,400,401],{"class":264}," --name=knecht",[254,403,404],{"class":264}," https:\u002F\u002Fraw.githubusercontent.com\u002Fknecht-works\u002Fknecht-cloud\u002Fmain\u002Fscripts\u002Flima-server.yaml\n",[254,406,408,410,413],{"class":256,"line":407},3,[254,409,395],{"class":260},[254,411,412],{"class":264}," start",[254,414,415],{"class":264}," knecht\n",[116,417,419],{"id":418},"run-the-installer-inside-the-vm","Run the Installer inside the VM",[245,421,423],{"className":247,"code":422,"language":249,"meta":250,"style":250},"limactl shell knecht\ncurl -fsSL https:\u002F\u002Fraw.githubusercontent.com\u002Fknecht-works\u002Fknecht-cloud\u002Fmain\u002Fscripts\u002Finstall.sh | sudo bash\n",[228,424,425,434],{"__ignoreMap":250},[254,426,427,429,432],{"class":256,"line":257},[254,428,395],{"class":260},[254,430,431],{"class":264}," shell",[254,433,415],{"class":264},[254,435,436,438,440,442,444,447],{"class":256,"line":392},[254,437,261],{"class":260},[254,439,265],{"class":264},[254,441,268],{"class":264},[254,443,272],{"class":271},[254,445,446],{"class":260}," sudo",[254,448,275],{"class":264},[96,450,451],{},"The installer asks for the domain, the same as on Linux.",[116,453,455],{"id":454},"make-the-mac-reachable","Make the Mac Reachable",[96,457,458],{},"The three steps from the Linux install apply unchanged: DNS records, ports, dashboard. On a home network, two things come on top:",[124,460,461,464],{},[127,462,463],{},"Forward TCP ports 80 and 443 on your router to the Mac, and give the Mac a fixed address in the router.",[127,465,466],{},"Home connections change their public IP over time. Point the two DNS records at a dynamic DNS name, or get a static IP from your ISP.",[116,468,470],{"id":469},"after-a-reboot","After a Reboot",[96,472,473,474,477,478,480,481,484,485,109],{},"The VM does not start on its own. Run ",[228,475,476],{},"limactl start knecht"," after a macOS reboot, the containers inside come back up by themselves. ",[228,479,281],{}," and ",[228,482,483],{},"\u002Fdata\u002Fknecht"," live inside the VM, reachable through ",[228,486,487],{},"limactl shell knecht",[116,489,491],{"id":490},"local-domain-for-testing","Local Domain for Testing",[96,493,494],{},"To try Knecht on a Mac without any DNS setup, install it under a local domain. GitHub cannot reach the instance then, so webhooks never arrive and GitHub triggers do not fire. Manual and scheduled triggers work.",[308,496,498,503,520,524,535,541,545,576],{"level":497},"4",[499,500,502],"h4",{"id":501},"use-lvhme-as-the-domain","Use lvh.me as the domain",[96,504,505,508,509,512,513,516,517,519],{},[228,506,507],{},"lvh.me"," is a public domain that, together with all its subdomains, always resolves to ",[228,510,511],{},"127.0.0.1",". It needs no DNS setup and no entries in ",[228,514,515],{},"\u002Fetc\u002Fhosts",". Enter ",[228,518,507],{}," when the installer asks for the domain, then the dashboard and every preview subdomain work locally. Ports 80 and 443 on the Mac must be free.",[499,521,523],{"id":522},"switch-caddy-to-its-internal-ca","Switch Caddy to its internal CA",[96,525,526,527,530,531,534],{},"Let's Encrypt cannot issue certificates for a local domain. Inside the VM, edit ",[228,528,529],{},"\u002Fopt\u002Fknecht\u002FCaddyfile"," so both site blocks use ",[228,532,533],{},"tls internal",":",[245,536,539],{"className":537,"code":538,"language":327},[325],"{$KNECHT_BASE_DOMAIN} {\n    tls internal\n    reverse_proxy knecht:3000\n}\n\nhttps:\u002F\u002F {\n    tls internal {\n        on_demand\n    }\n    reverse_proxy knecht:3000\n}\n",[228,540,538],{"__ignoreMap":250},[499,542,544],{"id":543},"restart-caddy-and-open-the-dashboard","Restart Caddy and open the dashboard",[245,546,548],{"className":247,"code":547,"language":249,"meta":250,"style":250},"cd \u002Fopt\u002Fknecht && sudo docker compose restart caddy\n",[228,549,550],{"__ignoreMap":250},[254,551,552,556,559,562,564,567,570,573],{"class":256,"line":257},[254,553,555],{"class":554},"s2Zo4","cd",[254,557,558],{"class":264}," \u002Fopt\u002Fknecht",[254,560,561],{"class":271}," &&",[254,563,446],{"class":260},[254,565,566],{"class":264}," docker",[254,568,569],{"class":264}," compose",[254,571,572],{"class":264}," restart",[254,574,575],{"class":264}," caddy\n",[96,577,578,579,582],{},"Open ",[228,580,581],{},"https:\u002F\u002Flvh.me"," and accept the certificate warning.",[96,584,585,586,588,589,109],{},"Once the dashboard opens, continue with ",[100,587,27],{"href":28},". Updating, backups, and pre-releases are on ",[100,590,31],{"href":32},[592,593,594],"style",{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}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 .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}",{"title":250,"searchDepth":392,"depth":392,"links":596},[597,603,608],{"id":113,"depth":392,"text":114,"children":598},[599,600,601,602],{"id":118,"depth":407,"text":119},{"id":154,"depth":407,"text":155},{"id":169,"depth":407,"text":170},{"id":220,"depth":407,"text":221},{"id":239,"depth":392,"text":240,"children":604},[605,606,607],{"id":313,"depth":407,"text":314},{"id":338,"depth":407,"text":339},{"id":345,"depth":407,"text":346},{"id":358,"depth":392,"text":145,"children":609},[610,611,612,613,614],{"id":372,"depth":407,"text":373},{"id":418,"depth":407,"text":419},{"id":454,"depth":407,"text":455},{"id":469,"depth":407,"text":470},{"id":490,"depth":407,"text":491},"Run Knecht on your own infrastructure.","md",{},true,{"title":23,"description":615},"ctgCL8Yg0wZlQrN4_jQC9cVc1syeg4Th56xXEIxwTDI",[622,624],{"title":19,"path":20,"stem":21,"description":623,"children":-1},"The pieces you meet in the dashboard and how they fit together.",{"title":27,"path":28,"stem":29,"description":625,"children":-1},"Configure your Knecht instance after installation.",1790265015624]