github.com/symfony-cli/symfony-cli@v0.0.0-20240514161054-ece2df437dfa/local/php/fpm.go (about) 1 /* 2 * Copyright (c) 2021-present Fabien Potencier <fabien@symfony.com> 3 * 4 * This file is part of Symfony CLI project 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU Affero General Public License as 8 * published by the Free Software Foundation, either version 3 of the 9 * License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU Affero General Public License for more details. 15 * 16 * You should have received a copy of the GNU Affero General Public License 17 * along with this program. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 package php 21 22 import ( 23 "bytes" 24 "fmt" 25 "os" 26 "os/exec" 27 "os/user" 28 "path/filepath" 29 "strings" 30 31 "github.com/hashicorp/go-version" 32 "github.com/symfony-cli/terminal" 33 ) 34 35 func (p *Server) defaultFPMConf() string { 36 logLevel := "notice" 37 if terminal.IsDebug() { 38 logLevel = "debug" 39 } 40 userConfig := "" 41 // when root, we need to configure the user in FPM configuration 42 if os.Geteuid() == 0 { 43 uid := "nobody" 44 gid := "nobody" 45 users := []string{ 46 "www-data", // debian-like, alpine 47 "apache", // fedora 48 "http", // pld linux 49 "www", // freebsd? 50 "_www", // macOS 51 } 52 // we prefer to use the currently logged-in user (which might not be the current user when using sudo) 53 // also, you might not be logged in (when running in a Docker container for instance), in which case, we need to fall back to a "default" user 54 cmd := exec.Command("logname") 55 var out bytes.Buffer 56 cmd.Stdout = &out 57 err := cmd.Run() 58 if err == nil { 59 users = append([]string{strings.TrimSpace(out.String())}, users...) 60 } 61 for _, name := range users { 62 u, err := user.Lookup(name) 63 if err == nil { 64 uid = u.Uid 65 gid = u.Gid 66 break 67 } 68 } 69 userConfig = fmt.Sprintf("user = %s\ngroup = %s", uid, gid) 70 } 71 minVersion, _ := version.NewVersion("7.3.0") 72 workerConfig := "" 73 logLimit := "" 74 if p.Version.FullVersion.GreaterThanOrEqual(minVersion) { 75 workerConfig = "decorate_workers_output = no" 76 // see https://github.com/docker-library/php/pull/725#issuecomment-443540114 77 logLimit = "log_limit = 8192" 78 } 79 listen := p.addr 80 if listen[0] == ':' { 81 listen = "127.0.0.1" + listen 82 } 83 return fmt.Sprintf(` 84 [global] 85 error_log = /dev/fd/2 86 log_level = %s 87 daemonize = no 88 %s 89 90 [www] 91 %s 92 listen = %s 93 listen.allowed_clients = 127.0.0.1 94 pm = dynamic 95 pm.max_children = 5 96 pm.start_servers = 2 97 pm.min_spare_servers = 1 98 pm.max_spare_servers = 3 99 pm.status_path = /__php-fpm-status__ 100 101 ; Ensure worker stdout and stderr are sent to the main error log 102 catch_workers_output = yes 103 %s 104 105 php_admin_value[error_log] = /dev/fd/2 106 php_admin_flag[log_errors] = on 107 108 ; we want to expose env vars (like in FOO=bar symfony server:start) 109 clear_env = no 110 111 env['PGGSSENCMODE'] = disable 112 env['LC_ALL'] = C 113 `, logLevel, logLimit, userConfig, listen, workerConfig) 114 } 115 116 func (p *Server) fpmConfigFile() string { 117 path := filepath.Join(p.homeDir, fmt.Sprintf("php/%s/fpm-%s.ini", name(p.projectDir), p.Version.Version)) 118 if _, err := os.Stat(filepath.Dir(path)); os.IsNotExist(err) { 119 _ = os.MkdirAll(filepath.Dir(path), 0755) 120 } 121 return path 122 }