[{"data":1,"prerenderedAt":492},["ShallowReactive",2],{"docs-nav":3,"docs:\u002Fdocs\u002Fmulti-project-hosts":139},[4,7,10,13,16,19,22,25,28,31,34,37,40,43,46,49,52,55,58,61,64,67,70,73,76,79,82,85,88,91,94,97,100,103,106,109,112,115,118,121,124,127,130,133,136],{"path":5,"title":6},"\u002Fdocs\u002Faccess-gating","Protect a local route",{"path":8,"title":9},"\u002Fdocs\u002Farchitecture\u002Fsecurity-and-trust","Security and trust",{"path":11,"title":12},"\u002Fdocs\u002Fconcepts\u002Fbuilds-and-deployments","Build and deploy",{"path":14,"title":15},"\u002Fdocs\u002Fconcepts\u002Fconfiguration-ownership","Where configuration belongs",{"path":17,"title":18},"\u002Fdocs\u002Fconcepts\u002Fenvironments-and-secrets","Environment values and secrets",{"path":20,"title":21},"\u002Fdocs\u002Fconcepts\u002Fmental-model","How projects fit together",{"path":23,"title":24},"\u002Fdocs\u002Fconcepts\u002Fplans-and-apply","Plans and apply",{"path":26,"title":27},"\u002Fdocs\u002Fconcepts\u002Ftargets-and-runtimes","Choose a target and runtime",{"path":29,"title":30},"\u002Fdocs\u002Fcontribute\u002Freleases","Publish a release",{"path":32,"title":33},"\u002Fdocs\u002Fdevelopment-mounts","Development mounts",{"path":35,"title":36},"\u002Fdocs\u002Fgetting-started","Getting started",{"path":38,"title":39},"\u002Fdocs\u002Fhelp\u002Ffaq","FAQ",{"path":41,"title":42},"\u002Fdocs\u002Fhelp\u002Ftroubleshooting","Troubleshooting",{"path":44,"title":45},"\u002Fdocs\u002Fhow-to\u002Fdeploy-production","Prepare a deployment environment",{"path":47,"title":48},"\u002Fdocs\u002Fhow-to\u002Fswarm-cluster","Run on a multi-node Swarm",{"path":50,"title":51},"\u002Fdocs","mm documentation",{"path":53,"title":54},"\u002Fdocs\u002Fjobs-and-schedules","Jobs and schedules",{"path":56,"title":57},"\u002Fdocs\u002Flocal-dashboard","Local dashboard",{"path":59,"title":60},"\u002Fdocs\u002Flocal-https","Local HTTPS",{"path":62,"title":63},"\u002Fdocs\u002Flocal-services","Local services",{"path":65,"title":66},"\u002Fdocs\u002Fmcp","Let an AI agent work on your project",{"path":68,"title":69},"\u002Fdocs\u002Fmulti-project-hosts","Run multiple projects on one host",{"path":71,"title":72},"\u002Fdocs\u002Fonboarding","Set up a project",{"path":74,"title":75},"\u002Fdocs\u002Fopenbao","Use OpenBao",{"path":77,"title":78},"\u002Fdocs\u002Fproject\u002Fcontributing","Contributing",{"path":80,"title":81},"\u002Fdocs\u002Fproject\u002Flicense","License",{"path":83,"title":84},"\u002Fdocs\u002Fproject\u002Fsecurity","Security",{"path":86,"title":87},"\u002Fdocs\u002Freference\u002Fcapability-matrix","Supported features and platforms",{"path":89,"title":90},"\u002Fdocs\u002Freference\u002Fcli","CLI command reference",{"path":92,"title":93},"\u002Fdocs\u002Freference\u002Fconfiguration","Configuration",{"path":95,"title":96},"\u002Fdocs\u002Freference\u002Fenvironment-variables","Environment variables",{"path":98,"title":99},"\u002Fdocs\u002Freference\u002Ferrors-and-exit-codes","Errors and exit codes",{"path":101,"title":102},"\u002Fdocs\u002Freference\u002Fknown-issues","Known limitations",{"path":104,"title":105},"\u002Fdocs\u002Fremote-access","Manage remote access",{"path":107,"title":108},"\u002Fdocs\u002Fremote-daemon","Set up a remote host",{"path":110,"title":111},"\u002Fdocs\u002Fruntime-observability","Status, logs, and commands",{"path":113,"title":114},"\u002Fdocs\u002Fsecret-delivery","Pass secrets to your app",{"path":116,"title":117},"\u002Fdocs\u002Fsecret-providers","Choose a secret store",{"path":119,"title":120},"\u002Fdocs\u002Fstart\u002Finstall","Install mm",{"path":122,"title":123},"\u002Fdocs\u002Fterminal-ui","Terminal UI",{"path":125,"title":126},"\u002Fdocs\u002Ftutorials\u002Fdotnet-web-api",".NET web API example",{"path":128,"title":129},"\u002Fdocs\u002Ftutorials\u002Ffirst-local-app","First local app",{"path":131,"title":132},"\u002Fdocs\u002Ftutorials\u002Flaravel-rust","Laravel and Rust example",{"path":134,"title":135},"\u002Fdocs\u002Ftutorials\u002Fnode-fullstack","Node full stack example",{"path":137,"title":138},"\u002Fdocs\u002Fvault","Use HashiCorp Vault",{"id":140,"title":69,"body":141,"description":485,"extension":486,"meta":487,"navigation":488,"path":68,"seo":489,"stem":490,"__hash__":491},"docs\u002Fdocs\u002Fmulti-project-hosts.md",{"type":142,"value":143,"toc":478},"minimark",[144,148,162,167,178,189,192,196,223,389,399,408,412,418,422,456,459,463,474],[145,146,147],"p",{},"One mm host can run several trusted projects. Projects share the daemon,\nruntime, and host services, while mm tracks their workloads separately by project\nUUID. This prevents accidental cross-project changes; it is not isolation for\nuntrusted tenants.",[145,149,150,151,156,157,161],{},"Start with ",[152,153,155],"a",{"href":154},".\u002Fremote-daemon","remote host setup"," and\n",[152,158,160],{"href":159},".\u002Fremote-access","remote access",". Use Docker Compose or rootless Podman\nCompose for this setup.",[163,164,166],"h2",{"id":165},"host-layout","Host layout",[168,169,175],"pre",{"className":170,"code":172,"language":173,"meta":174},[171],"language-text","\u002Fetc\u002Fmm\u002Fmmd.json                         daemon configuration\n\u002Fetc\u002Fmm\u002Fhost.yaml                        enrolled projects, ceilings, break-glass keys\n\u002Fetc\u002Fssh\u002Fmm_authorized_keys          written by mmd from each project's users file\n\u002Fvar\u002Flib\u002Fmm\u002Fprojects\u002F\u003Cuuid>\u002Frepo.git     mmd's mirror of the project's origin\n\u002Fvar\u002Flib\u002Fmm\u002Fprojects\u002F\u003Cuuid>\u002Faccess\u002F      reconciled users per environment\n\u002Fsrv\u002Fmm\u002Fprojects\u002F\u003Cuuid>\u002F\u003Cenv>\u002F\u003Csha12>\u002F   one checkout per deployed commit\n\u002Fvar\u002Flib\u002Fmm-home\u002F                        target and shared-service state\n","text","",[176,177,172],"code",{"__ignoreMap":174},[145,179,180,181,184,185,188],{},"Configuration is root-owned with mode ",[176,182,183],{},"0600",". Nobody edits checkouts on the\nhost: ",[176,186,187],{},"mmd"," fetches each commit from the origin pinned for the project and\nkeeps one immutable directory per commit.",[145,190,191],{},"For rootful Docker, use the supplied hardened root system unit. For rootless\nPodman, use a system unit running as a dedicated runtime owner with private\nstate. Do not tie a shared host to a developer's login session.",[163,193,195],{"id":194},"enroll-projects","Enroll projects",[145,197,198,199,202,203,206,207,210,211,214,215,218,219,222],{},"Enroll each project by running ",[176,200,201],{},"mm target setup"," with ",[176,204,205],{},"--origin"," from that\nproject's checkout, as in ",[152,208,155],{"href":209},".\u002Fremote-daemon#set-up-the-host",".\nSetup adds the project to ",[176,212,213],{},"\u002Fetc\u002Fmm\u002Fhost.yaml"," and creates its deploy key,\nkeeping the other projects' entries. Each project is one entry under\n",[176,216,217],{},"projects:",", keyed by the UUID in its ",[176,220,221],{},".config\u002Fmm.yaml",":",[168,224,228],{"className":225,"code":226,"language":227,"meta":174,"style":174},"language-yaml shiki shiki-themes mm","projects:\n  019c527b-6242-7b43-bfd4-bd60e27c1de3:\n    name: shop\n    origin: git@github.com:acme\u002Fshop.git\n    origin-host-key: ssh-ed25519 AAAA…\n    environments: [staging, production]\n  019c527b-6242-7b43-bfd4-bd60e27c1de4:\n    name: billing\n    origin: git@github.com:acme\u002Fbilling.git\n    origin-host-key: ssh-ed25519 AAAA…\n    environments: [production]\n    ceiling:\n      production: { level: deploy }\n","yaml",[176,229,230,243,251,263,274,285,308,316,326,336,345,359,367],{"__ignoreMap":174},[231,232,235,239],"span",{"class":233,"line":234},"line",1,[231,236,238],{"class":237},"sWZmh","projects",[231,240,242],{"class":241},"sIbZ0",":\n",[231,244,246,249],{"class":233,"line":245},2,[231,247,248],{"class":237},"  019c527b-6242-7b43-bfd4-bd60e27c1de3",[231,250,242],{"class":241},[231,252,254,257,259],{"class":233,"line":253},3,[231,255,256],{"class":237},"    name",[231,258,222],{"class":241},[231,260,262],{"class":261},"sv8ni"," shop\n",[231,264,266,269,271],{"class":233,"line":265},4,[231,267,268],{"class":237},"    origin",[231,270,222],{"class":241},[231,272,273],{"class":261}," git@github.com:acme\u002Fshop.git\n",[231,275,277,280,282],{"class":233,"line":276},5,[231,278,279],{"class":237},"    origin-host-key",[231,281,222],{"class":241},[231,283,284],{"class":261}," ssh-ed25519 AAAA…\n",[231,286,288,291,293,296,299,302,305],{"class":233,"line":287},6,[231,289,290],{"class":237},"    environments",[231,292,222],{"class":241},[231,294,295],{"class":241}," [",[231,297,298],{"class":261},"staging",[231,300,301],{"class":241},",",[231,303,304],{"class":261}," production",[231,306,307],{"class":241},"]\n",[231,309,311,314],{"class":233,"line":310},7,[231,312,313],{"class":237},"  019c527b-6242-7b43-bfd4-bd60e27c1de4",[231,315,242],{"class":241},[231,317,319,321,323],{"class":233,"line":318},8,[231,320,256],{"class":237},[231,322,222],{"class":241},[231,324,325],{"class":261}," billing\n",[231,327,329,331,333],{"class":233,"line":328},9,[231,330,268],{"class":237},[231,332,222],{"class":241},[231,334,335],{"class":261}," git@github.com:acme\u002Fbilling.git\n",[231,337,339,341,343],{"class":233,"line":338},10,[231,340,279],{"class":237},[231,342,222],{"class":241},[231,344,284],{"class":261},[231,346,348,350,352,354,357],{"class":233,"line":347},11,[231,349,290],{"class":237},[231,351,222],{"class":241},[231,353,295],{"class":241},[231,355,356],{"class":261},"production",[231,358,307],{"class":241},[231,360,362,365],{"class":233,"line":361},12,[231,363,364],{"class":237},"    ceiling",[231,366,242],{"class":241},[231,368,370,373,375,378,381,383,386],{"class":233,"line":369},13,[231,371,372],{"class":237},"      production",[231,374,222],{"class":241},[231,376,377],{"class":241}," {",[231,379,380],{"class":237}," level",[231,382,222],{"class":241},[231,384,385],{"class":261}," deploy",[231,387,388],{"class":241}," }\n",[145,390,391,392,395,396,398],{},"After editing the file by hand, run ",[176,393,394],{},"mmd access validate",", then restart ",[176,397,187],{},".\nA project the host does not list is refused, whatever its users file says.",[145,400,401,404,405,407],{},[176,402,403],{},"mm target setup plan"," and its reviewed apply command also install the selected\nruntime. Docker setup supports the configured Debian\u002FUbuntu repository;\nrootless Podman requires a working user namespace. Setup installs the selected\nengine rather than silently switching to another. Setup installs the remote\naccess layer only with Docker, because ",[176,406,187],{}," runs as root; for rootless Podman,\ninstall it by hand as described above.",[163,409,411],{"id":410},"give-developers-access","Give developers access",[145,413,414,415,417],{},"Each project's users file decides who may reach it, per environment; see\n",[152,416,160],{"href":159},". One SSH key can belong to users of several\nprojects, and each project only sees its own grants. Two projects can use the\nsame service names without sharing resources. Project dashboard names include a\nUUID to avoid name collisions.",[163,419,421],{"id":420},"remove-a-project","Remove a project",[423,424,425,429,445],"ol",{},[426,427,428],"li",{},"Stop and remove its workloads while the project is still enrolled. Check\nthat other projects remain healthy.",[426,430,431,432,434,435,437,438,440,441,444],{},"Remove its entry from ",[176,433,213],{},", run ",[176,436,394],{},", and\nrestart ",[176,439,187],{},". Its users lose access at once, and ",[176,442,443],{},"authorized_keys"," drops\nkeys no other project lists.",[426,446,447,448,451,452,455],{},"Archive ",[176,449,450],{},"\u002Fvar\u002Flib\u002Fmm\u002Fprojects\u002F\u003Cuuid>"," and ",[176,453,454],{},"\u002Fsrv\u002Fmm\u002Fprojects\u002F\u003Cuuid>","\naccording to your retention policy. Removing the enrollment does not delete\nthem.",[145,457,458],{},"Keep shared services, target state, daemon identity, and audit history. Do not\nremove a shared provider or data volume merely because one project leaves.",[163,460,462],{"id":461},"recover-after-a-host-failure","Recover after a host failure",[145,464,465,466,469,470,473],{},"Retain ",[176,467,468],{},"\u002Fvar\u002Flib\u002Fmm",", ",[176,471,472],{},"\u002Fvar\u002Flib\u002Fmm-home",", and engine volumes. Inspect operation\nand audit state before making a fresh plan; an interrupted apply may have an\nunknown outcome. Restore a corrupt shared database from backup rather than\ndeleting it to clear an error. Concurrent deployments may wait for the host's\noperation lock; this protects shared route and service updates.",[475,476,477],"style",{},"html pre.shiki code .sWZmh, html code.shiki .sWZmh{--shiki-default:var(--mm-code-key)}html pre.shiki code .sIbZ0, html code.shiki .sIbZ0{--shiki-default:var(--mm-code-punctuation)}html pre.shiki code .sv8ni, html code.shiki .sv8ni{--shiki-default:var(--mm-code-string)}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);}",{"title":174,"searchDepth":245,"depth":245,"links":479},[480,481,482,483,484],{"id":165,"depth":245,"text":166},{"id":194,"depth":245,"text":195},{"id":410,"depth":245,"text":411},{"id":420,"depth":245,"text":421},{"id":461,"depth":245,"text":462},"Enroll several projects on one host and remove one without affecting the others.","md",{},true,{"title":69,"description":485},"docs\u002Fmulti-project-hosts","Qhc3pZVqrUPXawVUJ4_oFy5D73Xf48cmXvu1Y7mPSm8",1794512546198]