@@ -146,7 +146,7 @@ func New(options Options) Agent {
146
146
logger : options .Logger ,
147
147
closeCancel : cancelFunc ,
148
148
closed : make (chan struct {}),
149
- envVars : options .EnvironmentVariables ,
149
+ environmentVariables : options .EnvironmentVariables ,
150
150
client : options .Client ,
151
151
exchangeToken : options .ExchangeToken ,
152
152
filesystem : options .Filesystem ,
@@ -169,6 +169,8 @@ func New(options Options) Agent {
169
169
prometheusRegistry : prometheusRegistry ,
170
170
metrics : newAgentMetrics (prometheusRegistry ),
171
171
}
172
+ a .serviceBanner .Store (new (codersdk.ServiceBannerConfig ))
173
+ a .sessionToken .Store (new (string ))
172
174
a .init (ctx )
173
175
return a
174
176
}
@@ -196,7 +198,7 @@ type agent struct {
196
198
closeMutex sync.Mutex
197
199
closed chan struct {}
198
200
199
- envVars map [string ]string
201
+ environmentVariables map [string ]string
200
202
201
203
manifest atomic.Pointer [agentsdk.Manifest ] // manifest is atomic because values can change after reconnection.
202
204
reportMetadataInterval time.Duration
@@ -235,14 +237,16 @@ func (a *agent) TailnetConn() *tailnet.Conn {
235
237
}
236
238
237
239
func (a * agent ) init (ctx context.Context ) {
238
- sshSrv , err := agentssh .NewServer (ctx , a .logger .Named ("ssh-server" ), a .prometheusRegistry , a .filesystem , a .sshMaxTimeout , "" )
240
+ sshSrv , err := agentssh .NewServer (ctx , a .logger .Named ("ssh-server" ), a .prometheusRegistry , a .filesystem , & agentssh.Config {
241
+ MaxTimeout : a .sshMaxTimeout ,
242
+ MOTDFile : func () string { return a .manifest .Load ().MOTDFile },
243
+ ServiceBanner : func () * codersdk.ServiceBannerConfig { return a .serviceBanner .Load () },
244
+ UpdateEnv : a .updateCommandEnv ,
245
+ WorkingDirectory : func () string { return a .manifest .Load ().Directory },
246
+ })
239
247
if err != nil {
240
248
panic (err )
241
249
}
242
- sshSrv .Env = a .envVars
243
- sshSrv .AgentToken = func () string { return * a .sessionToken .Load () }
244
- sshSrv .Manifest = & a .manifest
245
- sshSrv .ServiceBanner = & a .serviceBanner
246
250
a .sshServer = sshSrv
247
251
a .scriptRunner = agentscripts .New (agentscripts.Options {
248
252
LogDir : a .logDir ,
@@ -879,6 +883,83 @@ func (a *agent) run(ctx context.Context) error {
879
883
return eg .Wait ()
880
884
}
881
885
886
+ // updateCommandEnv updates the provided command environment with the
887
+ // following set of environment variables:
888
+ // - Predefined workspace environment variables
889
+ // - Environment variables currently set (overriding predefined)
890
+ // - Environment variables passed via the agent manifest (overriding predefined and current)
891
+ // - Agent-level environment variables (overriding all)
892
+ func (a * agent ) updateCommandEnv (current []string ) (updated []string , err error ) {
893
+ manifest := a .manifest .Load ()
894
+ if manifest == nil {
895
+ return nil , xerrors .Errorf ("no manifest" )
896
+ }
897
+
898
+ executablePath , err := os .Executable ()
899
+ if err != nil {
900
+ return nil , xerrors .Errorf ("getting os executable: %w" , err )
901
+ }
902
+ unixExecutablePath := strings .ReplaceAll (executablePath , "\\ " , "/" )
903
+
904
+ // Define environment variables that should be set for all commands,
905
+ // and then merge them with the current environment.
906
+ envs := map [string ]string {
907
+ // Set env vars indicating we're inside a Coder workspace.
908
+ "CODER" : "true" ,
909
+ "CODER_WORKSPACE_NAME" : manifest .WorkspaceName ,
910
+ "CODER_WORKSPACE_AGENT_NAME" : manifest .AgentName ,
911
+
912
+ // Specific Coder subcommands require the agent token exposed!
913
+ "CODER_AGENT_TOKEN" : * a .sessionToken .Load (),
914
+
915
+ // Git on Windows resolves with UNIX-style paths.
916
+ // If using backslashes, it's unable to find the executable.
917
+ "GIT_SSH_COMMAND" : fmt .Sprintf ("%s gitssh --" , unixExecutablePath ),
918
+ // Hide Coder message on code-server's "Getting Started" page
919
+ "CS_DISABLE_GETTING_STARTED_OVERRIDE" : "true" ,
920
+ }
921
+
922
+ // This adds the ports dialog to code-server that enables
923
+ // proxying a port dynamically.
924
+ // If this is empty string, do not set anything. Code-server auto defaults
925
+ // using its basepath to construct a path based port proxy.
926
+ if manifest .VSCodePortProxyURI != "" {
927
+ envs ["VSCODE_PROXY_URI" ] = manifest .VSCodePortProxyURI
928
+ }
929
+
930
+ // Allow any of the current env to override what we defined above.
931
+ for _ , env := range current {
932
+ parts := strings .SplitN (env , "=" , 2 )
933
+ if len (parts ) != 2 {
934
+ continue
935
+ }
936
+ if _ , ok := envs [parts [0 ]]; ! ok {
937
+ envs [parts [0 ]] = parts [1 ]
938
+ }
939
+ }
940
+
941
+ // Load environment variables passed via the agent manifest.
942
+ // These override all variables we manually specify.
943
+ for k , v := range manifest .EnvironmentVariables {
944
+ // Expanding environment variables allows for customization
945
+ // of the $PATH, among other variables. Customers can prepend
946
+ // or append to the $PATH, so allowing expand is required!
947
+ envs [k ] = os .ExpandEnv (v )
948
+ }
949
+
950
+ // Agent-level environment variables should take over all. This is
951
+ // used for setting agent-specific variables like CODER_AGENT_TOKEN
952
+ // and GIT_ASKPASS.
953
+ for k , v := range a .environmentVariables {
954
+ envs [k ] = v
955
+ }
956
+
957
+ for k , v := range envs {
958
+ updated = append (updated , fmt .Sprintf ("%s=%s" , k , v ))
959
+ }
960
+ return updated , nil
961
+ }
962
+
882
963
func (a * agent ) wireguardAddresses (agentID uuid.UUID ) []netip.Prefix {
883
964
if len (a .addresses ) == 0 {
884
965
return []netip.Prefix {
@@ -1314,7 +1395,7 @@ func (a *agent) manageProcessPriorityLoop(ctx context.Context) {
1314
1395
}
1315
1396
}()
1316
1397
1317
- if val := a .envVars [EnvProcPrioMgmt ]; val == "" || runtime .GOOS != "linux" {
1398
+ if val := a .environmentVariables [EnvProcPrioMgmt ]; val == "" || runtime .GOOS != "linux" {
1318
1399
a .logger .Debug (ctx , "process priority not enabled, agent will not manage process niceness/oom_score_adj " ,
1319
1400
slog .F ("env_var" , EnvProcPrioMgmt ),
1320
1401
slog .F ("value" , val ),
0 commit comments