TekOnline

How I Got an Azure DevOps / TFS Environment Agent Working on a Server With No Internet

If you are trying to add a self-hosted Azure DevOps or TFS agent to an environment and the server has no internet access, there is a good chance you will hit a few annoying roadblocks.

I recently worked through this and thought I would write it up so the next person has a clearer path.

This article avoids sharing any secrets, tokens, usernames, or internal details. It focuses on the process and the gotchas.


The situation

I was trying to register a Windows agent for an environment in TFS / Azure DevOps Server.

The portal-generated script was trying to:

  • create an agent folder
  • download the agent zip from the internet
  • extract it
  • run config.cmd

That is fine on a normal server, but on an isolated machine the download step fails straight away.

On top of that, I ran into old agent cleanup issues and then authorization issues when trying to configure the new one.


The first problem: no internet access

The generated script usually contains a line like this:

$Uri='https://vstsagentpackage.azureedge.net/agent/.../vsts-agent-win-x64-<version>.zip'
$WebClient.DownloadFile($Uri, $agentZip)

That obviously will not work on a server with no internet.

The fix

Download the correct agent zip on another machine first, then copy it onto the server manually, for example by:

  • USB
  • internal file share
  • approved package transfer method

Then replace the online download step with a local file copy.

Example approach:

$agentZip="$PWD\agent.zip"
$localZip="C:\temp\vsts-agent-win-x64-4.269.0.zip"If(-NOT (Test-Path $localZip)){
throw "Offline agent package not found at $localZip"
}Copy-Item $localZip $agentZip -Force
Add-Type -AssemblyName System.IO.Compression.FileSystem
[System.IO.Compression.ZipFile]::ExtractToDirectory($agentZip, "$PWD")

That removes the internet dependency for the installer package.


The second problem: old agent already configured

After extracting the agent, I hit:

Cannot configure the agent because it is already configured.
To reconfigure the agent, run 'config.cmd remove' first.

That means the extracted folder already contains agent config markers such as:

  • .agent
  • .credentials
  • .credentials_rsaparams

What I found

Even if the agent service was no longer visible in Windows, the extracted folder itself could still be configured.

Checking with:

dir -Force

helped confirm this.


The third problem: remove did not work cleanly

Trying to remove the old config with Integrated auth gave me an authorization error:

TF400813: The user '...' is not authorized to access this resource.

This was actually useful. It told me:

  • the server could reach TFS
  • authentication was happening
  • but the identity being used did not have permission to remove or register that resource

So the issue was no longer connectivity or extraction. It was permissions.


The fourth problem: deleting the old folder failed

I decided to wipe the extracted agent folder and start clean.

A normal PowerShell delete failed because of a very long nested path under _work, something like old task content inside node_modules.

Example failure looked like:

Could not find a part of the path ...

What worked

This worked perfectly:

cmd /c 'rmdir /s /q \\?\C:\temp\vsts-agent-win-x64-4.269.0'

That was the breakthrough.

The \\?\ prefix helps Windows handle ugly long-path cleanup problems much better than normal PowerShell deletion in some cases.

If you are fighting agent folder cleanup, try that first.


The fifth problem: the config script kept failing with TF400813

After fresh extraction, I tried running just the config portion.

Something like:

.\config.cmd --environment --environmentname "PROD_Server" --agent $env:COMPUTERNAME --runasservice --work "_work" --url "https://your-tfs-server/tfs" --collectionname "Your Collection" --projectname "Your Project" --auth Integrated

And I kept getting:

TF400813: The user '...' is not authorized to access this resource.

Important lesson

Just because you copied the script from the Create resource page does not mean your current Windows login has the permission needed to register the agent.

If you use:

--auth Integrated

then TFS uses the currently signed-in Windows identity.

So if that account does not have the right permissions to the environment, deployment pool, or project, registration fails.


What finally helped

The key insight was this:

Integrated auth uses your current Windows account

That is convenient, but only if the logged-in user already has the right permissions.

You may need to use different auth

Using a different auth mode can help, especially if another account has the correct access.

For example, trying a config command with a different auth type can prompt for credentials instead of silently using the current login.

That was the turning point for me.


Clean offline approach

Here is the general pattern I would recommend for an offline server.

1. Copy the agent zip to the server

Example:

C:\temp\vsts-agent-win-x64-4.269.0.zip

2. Create a fresh agent folder

Example:

cd C:\azagent
mkdir A1
cd A1

3. Extract the zip locally

Add-Type -AssemblyName System.IO.Compression.FileSystem
[System.IO.Compression.ZipFile]::ExtractToDirectory("C:\temp\vsts-agent-win-x64-4.269.0.zip", "$PWD")

4. Run only the config command

.\config.cmd --environment --environmentname "PROD_Server" --agent $env:COMPUTERNAME --runasservice --work "_work" --url "https://your-tfs-server/tfs" --collectionname "Your Collection" --projectname "Your Project" --auth Integrated

Or try another supported auth method if the current Windows identity is not enough.


Troubleshooting tips

1. Check whether the folder is already configured

dir -Force

Look for:

  • .agent
  • .credentials
  • .credentials_rsaparams

2. Check whether the service actually exists

Get-CimInstance Win32_Service | Where-Object { $_.Name -like "vstsagent*" } | Select Name, State, PathName

If nothing comes back, the service probably never installed.

3. Run config.cmd by itself

Do not hide it inside a huge one-liner while troubleshooting.

Run it directly so you can see the exact prompt or error.

4. If delete fails, use cmd with long-path support

cmd /c 'rmdir /s /q \\?\C:\path\to\agent-folder'

5. A TF400813 error is usually a permissions clue

That error often means:

  • authentication reached the server
  • but the identity does not have access to the requested resource

That is a very different problem from network failure.

My main takeaways

If I had to boil this down, it would be:

  • offline agent install is totally doable
  • the download step is easy to replace with a local zip
  • stale agent folders can block reconfiguration
  • PowerShell delete can choke on old _work content
  • cmd /c rmdir /s /q \\?\... is a lifesaver
  • TF400813 usually points to permissions, not package extraction
  • Integrated auth uses the currently logged-in Windows account
  • if that account lacks access, the script from the portal can still fail

Final thoughts

The hardest part was not the lack of internet. That part was easy once I switched to a local zip.

The real trap was assuming the generated script meant the current account must already be authorized. It does not. If the auth mode uses your current Windows identity, you still need the right access on the TFS side.

Hopefully this saves someone else a couple of hours.


Posted

in

by

Tags:

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *