@@ -3,14 +3,8 @@ import { promisify } from "util";
33
44const execAsync = promisify ( exec ) ;
55
6- /**
7- * Execute crontab command on the host system using nsenter to host namespaces
8- * This allows the Docker container to manage the host's crontab
9- */
106async function execHostCrontab ( command : string ) : Promise < string > {
117 try {
12- // Find the host's init process and use nsenter to execute commands in host context
13- // We use PID 1 which should be the host's init process due to pid: "host" in docker-compose
148 const { stdout } = await execAsync (
159 `nsenter -t 1 -m -u -i -n -p sh -c "${ command } "`
1610 ) ;
@@ -21,24 +15,17 @@ async function execHostCrontab(command: string): Promise<string> {
2115 }
2216}
2317
24- // Get the target user for crontab operations by detecting the host user dynamically
2518async function getTargetUser ( ) : Promise < string > {
2619 try {
27- // If explicitly set via environment variable, use that
2820 if ( process . env . HOST_CRONTAB_USER ) {
2921 return process . env . HOST_CRONTAB_USER ;
3022 }
3123
32- // Auto-detect the user by finding the owner of the docker socket
33- // This will typically be the user who started docker compose
3424 const { stdout } = await execAsync ( 'stat -c "%U" /var/run/docker.sock' ) ;
3525 const dockerSocketOwner = stdout . trim ( ) ;
3626
37- // If docker socket is owned by root, try to find the actual user
38- // by looking at process tree or mounted directories
3927 if ( dockerSocketOwner === 'root' ) {
4028 try {
41- // Try to detect from the mounted project directory ownership
4229 const projectDir = process . env . NEXT_PUBLIC_HOST_PROJECT_DIR ;
4330 if ( projectDir ) {
4431 const dirOwner = await execHostCrontab ( `stat -c "%U" "${ projectDir } "` ) ;
@@ -48,7 +35,6 @@ async function getTargetUser(): Promise<string> {
4835 console . warn ( "Could not detect user from project directory:" , error ) ;
4936 }
5037
51- // Fall back to looking for non-root users with home directories
5238 try {
5339 const users = await execHostCrontab ( 'getent passwd | grep ":/home/" | head -1 | cut -d: -f1' ) ;
5440 const firstUser = users . trim ( ) ;
@@ -59,14 +45,13 @@ async function getTargetUser(): Promise<string> {
5945 console . warn ( "Could not detect user from passwd:" , error ) ;
6046 }
6147
62- // Last resort - return root
6348 return 'root' ;
6449 }
6550
6651 return dockerSocketOwner ;
6752 } catch ( error ) {
6853 console . error ( "Error detecting target user:" , error ) ;
69- return 'root' ; // Safe fallback
54+ return 'root' ;
7055 }
7156}
7257
@@ -83,13 +68,11 @@ export async function readHostCrontab(): Promise<string> {
8368export async function writeHostCrontab ( content : string ) : Promise < boolean > {
8469 try {
8570 const user = await getTargetUser ( ) ;
86- // Ensure content ends with a newline (required by crontab)
8771 let finalContent = content ;
8872 if ( ! finalContent . endsWith ( '\n' ) ) {
8973 finalContent += '\n' ;
9074 }
9175
92- // Use base64 encoding to avoid all shell escaping issues
9376 const base64Content = Buffer . from ( finalContent ) . toString ( 'base64' ) ;
9477 await execHostCrontab ( `echo '${ base64Content } ' | base64 -d | crontab -u ${ user } -` ) ;
9578 return true ;
0 commit comments