VARNISH-CLI(7)
VARNISH-CLI(7) โ Varnish Command Line Interface ๐
okay bestie, buckle UP because this is the page where you learn that Varnish has a whole command line interface (CLI for the girlies who like acronyms) and it is iconic. Also lowkey this page is long so it comes in two parts โ this is part one, so don't go anywhere ๐ซถ
โจ NAME โจ
varnish-cli โ Varnish Command Line Interface. that's it, that's the name, slay ๐
๐ธ DESCRIPTION ๐ธ
So Varnish has this thing called a command line interface (CLI), and fr fr it can control and change like, most of the operational parameters and the configuration of Varnish โ and the whole point is you can do it without interrupting the running service. no downtime, no drama, we love to see it ๐ญ
Here's what you can do with the CLI, bestie:
- configuration โ you can upload, change and delete VCL files straight from the CLI. yes really. ๐
- parameters โ you can inspect and change all the various parameters Varnish has available, right through the CLI. the individual parameters each get their own lil writeup in the
varnishd(1)man page (go read it, iykyk). - bans โ okay so bans are filters that get applied to keep Varnish from serving stale content. when you issue a ban, Varnish will not serve any banned object from cache โ instead it re-fetches it from its backend servers. bye stale content ๐
- process management โ you can stop and start the cache (child) process through the CLI. and if the child process has crashed, you can also retrieve the latest stack trace. very main character of you to be able to do that tbh.
Now, how do you even get the CLI? If you invoke varnishd(1) with -T, -M or -d, the CLI will be available:
- In debug mode (
-d) the CLI will be in the foreground. - With
-Tyou can connect to it withvarnishadmortelnet. - With
-Mvarnishd will connect back to a listening service, pushing the CLI to that service.
Please see varnishd(1) for the details, bestie, that's where the tea is ๐
๐ฆ Syntax ๐ฆ
The Varnish CLI is similar to another command line interface you might know โ the Bourne Shell. Commands are usually terminated with a newline, and they may take arguments. The command and its arguments get tokenized before parsing, and because of that, any arguments containing spaces must be enclosed in double quotes. no cap.
Which means command parsing of:
help banner
is equivalent to:
"help" banner
because the double quotes only indicate the boundaries of the help token. it's giving "the quotes are just vibes and boundaries," periodt.
Within double quotes you can escape characters with \ (backslash). The \n, \r, and \t get translated to newlines, carriage returns, and tabs. Double quotes and backslashes themselves can be escaped with \" and \\ respectively.
To enter characters in octals use the \nnn syntax. Hexadecimals can be entered with the \xnn syntax. โจ
Commands may not end with a newline when a shell-style here document (here-document or heredoc) is used. The format of a here document is:
<< word
here document
word
word can be any continuous string you choose, as long as you make sure it doesn't appear naturally in the following here document. Traditionally EOF or END is used. classic choices, honestly ๐
๐ Quoting pitfalls ๐
ngl, integrating with the Varnish CLI can be sometimes surprising when quoting is involved. like, the way that quoting will just humble you?? ๐ญ
For instance, in Bourne Shell the delimiter used with here documents may or may not be separated by spaces from the << token:
cat <<EOF
hello
world
EOF
hello
world
With the Varnish CLI, the << and EOF tokens must be separated by at least one blank:
vcl.inline boot <<EOF
106 258
Message from VCC-compiler:
VCL version declaration missing
Update your VCL to Version 4 syntax, and add
vcl 4.0;
on the first line of the VCL files.
('<vcl.inline>' Line 1 Pos 1)
<<EOF
##---
Running VCC-compiler failed, exited with 2
VCL compilation failed
With the missing space, the here document can be added and the actual VCL can be loaded:
vcl.inline test << EOF
vcl 4.0;
backend be {
.host = "localhost";
}
EOF
200 14
VCL compiled.
A big difference with a shell here document is the handling of the << token. Just like command names can be quoted, the here document token keeps its meaning, even quoted:
vcl.inline test "<<" EOF
vcl 4.0;
backend be {
.host = "localhost";
}
EOF
200 14
VCL compiled.
When using a front-end to the Varnish-CLI like varnishadm, one must take into account the double expansion happening. First in the shell launching the varnishadm command and then in the Varnish CLI itself. When a command's parameter requires spaces, you need to ensure that the Varnish CLI will see the double quotes:
varnishadm param.set cc_command '"my alternate cc command"'
Change will take effect when VCL script is reloaded
Otherwise, if you don't quote the quotes, you may get a seemingly unrelated error message:
varnishadm param.set cc_command "my alternate cc command"
Unknown request.
Type 'help' for more info.
Too many parameters
Command failed with error code 105
If you are quoting with a here document, you must wrap it inside a shell multi-line argument:
varnishadm vcl.inline test '<< EOF
vcl 4.0;
backend be {
.host = "localhost";
}
EOF'
VCL compiled.
Another difference with a shell here document is that only one here document can be used on a single command line. For example, it is possible to do this in a shell script:
#!/bin/sh
cat << EOF1 ; cat << EOF2
hello
EOF1
world
EOF2
The expected output is:
hello
world
With the Varnish CLI, only the last parameter may use the here document form, which greatly restricts the number of commands that can effectively use them. Trying to use multiple here documents only takes the last one into account. so don't do that, bestie.
For example:
command argument << EOF1 << EOF2
heredoc1
EOF1
heredoc2
EOF2
This conceptually results in the following command line:
"command""argument""<<""EOF1""heredoc1\nEOF1\nheredoc2\n"
Other pitfalls include variable expansion of the shell invoking varnishadm, but this is not directly related to the Varnish CLI. If you get the quoting right you should be fine, even with complex commands. you got this ๐ช
๐ JSON ๐
A number of commands with informational responses support a -j parameter for JSON output, as specified below. The top-level structure of the JSON response is an array with these first three elements:
- A version number for the JSON format (integer)
- An array of strings that comprise the CLI command just received
- The time at which the response was generated, as a Unix epoch time in seconds with millisecond precision (floating point)
The remaining elements of the array form the data that are specific to the CLI command, and their structure and content depend on the command. it's giving "custom payload energy" โจ
For example, the response to status -j just contains a string in the top-level array indicating the state of the child process ("running", "stopped" and so forth):
[ 2, ["status", "-j"], 1538031732.632, "running"
]
The JSON responses to other commands may have longer lists of elements, which may have simple data types or form structured objects.
โ ๏ธ JSON output is only returned if command execution was successful. The output for an error response is always the same as it would have been for the command without the -j parameter. so like, no JSON for you if it fails, sorry bestie ๐
๐ Commands ๐
okay here's the actual command menu, the main event, the moment we've all been waiting for ๐
auth <response>
Authenticate. ๐
backend.list [-j] [-p] [<backend_pattern>]
List backends. the whole roster, we're checking who's healthy and who's not ๐
-palso shows probe status.-jspecifies JSON output.
Unless -j is specified for JSON output, the output format is five columns of dynamic width, separated by white space, with the fields:
- Backend name
- Admin: How health state is determined:
healthy: Set healthy throughbackend.set_health.sick: Set sick throughbackend.set_health.probe: Health state determined by a probe or some other dynamic mechanism.deleted: Backend has been deleted, but not yet cleaned up.
Admin has precedence over Health. periodt.
- Probe X/Y: X out of Y checks have succeeded
X and Y are backend specific and may represent probe checks, other backends or any other metric.
If there is no probe, or the director does not provide details on probe check results, 0/0 is output.
- Health: Probe health state
healthysick
If there is no probe, healthy is output.
- Last change: Timestamp when the health state last changed.
The health state reported here is generic. A backend's health may also depend on the context it is being used in (e.g. the object's hash), so the actual health state as visible from VCL (e.g. using std.healthy()) may differ. so like, don't come for me if the vibes don't match ๐
For -j, the object members should be self explanatory, matching the fields described above. probe_message has the format [X, Y, "state"] as described above for Probe. JSON Probe details (-j -p arguments) are director specific.
backend.set_health <backend_pattern> [auto|healthy|sick]
Set health status of backend(s) matching <backend_pattern>. time to play doctor ๐ฉบ
- With
auto, the health status is determined by a probe or some other dynamic mechanism, if any healthysets the backend as usablesicksets the backend as unusable
ban <field> <operator> <arg> [&& <field> <oper> <arg> ...]
Mark obsolete all objects where all the conditions match.
See std.ban() for details. it's giving "filter the whole cache" energy ๐ฅ
ban.list [-j]
List the active bans. here's who's currently cancelled ๐
Unless -j is specified for JSON output, the output format is:
- Time the ban was issued.
- Objects referencing this ban.
Cif ban is completed = no further testing against it.- if lurker debugging is enabled:
Rforreq.*testsOforobj.*tests- Pointer to ban object
- Ban specification
Durations of ban specifications get normalized, for example "7d" gets changed into "1w". yes, it does the math for you, iconic ๐ง
banner
Print welcome banner. say hi back bestie ๐ซถ
help [-j|<command>]
Show command/protocol help.
-jspecifies JSON output.
panic.clear [-z]
Clear the last panic, if any. -z will clear related varnishstat counter(s). we're wiping the tears and the counters ๐ญ
panic.show [-j]
Return the last panic, if any.
-jspecifies JSON output โ the panic message is returned as an unstructured JSON string.
param.reset [-j] <param>
Reset parameter to default value.
The JSON output is the same as param.show -j <param> and contains the updated value as it would be represented by a subsequent execution of param.show. so it's showing you the future, lowkey ๐ฎ
param.set [-j] <param> <value>
Set parameter value.
The JSON output is the same as param.show -j <param> and contains the updated value as it would be represented by a subsequent execution of param.show.
and that's where part one wraps up โ there's more coming, so stay tuned bestie, don't go anywhere ๐
This is lowkey the move when you wanna come back later and prove a parameter value didn't change, and to yoink the value straight out of the JSON output so you can set that parameter back to exactly the vibe you wanted. ๐ซถ
๐ธ param.show [-l|-j] [<param>|changed] ๐ธ
Peek at parameters and their values. Very demure, very informative.
- the long form with
-lspills the extra tea: documentation plus minimum, maximum and default values, if those are defined for the parameter ๐ - JSON output is specified with
-j, and yes, the long-form info is included in it. Only one of-lor-jis permitted, so don't get greedy ๐ - name a
<param>and you get only that one parameter, no extras - say
changedand you get only the parameters whose values differ from their defaults โ it's giving "okay what did I even touch" ๐
๐ฆ pid [-j] ๐ฆ
Shows the pid of the master process, and the worker too if it's running. Two for the price of one.
-j specifies JSON output.
โจ ping [-j] [<timestamp>] โจ
Keeps the connection alive. Just checking in, bestie, u up?
The response is formatted as JSON if -j is specified.
๐ quit ๐
Close connection. That's it, that's the whole command. Slay, goodbye.
๐ฅ start ๐ฅ
Start the Varnish cache process. Rise and grind.
โญ status [-j] โญ
Check status of the Varnish cache process. Vibe check, but for daemons.
-j specifies JSON output.
๐
stop ๐
Stop the Varnish cache process. Going to bed, don't text.
๐ storage.list [-j] ๐
List storage devices. Inventory era.
-j specifies JSON output.
๐ง vcl.deps [-j] ๐ง
List all loaded configuration and their dependencies. It's giving family tree.
Unless -j is specified for JSON output, the output format is up to two columns of dynamic width separated by white space, with the fields:
VCL: a VCL programDependency: another VCL program it depends on
Heads up: only direct dependencies are listed, and VCLs with multiple dependencies are listed multiple times. ๐
๐ vcl.discard <name_pattern>... ๐
Unload the named configurations (when possible). Manifesting a clean unload.
Unload the named configurations and labels matching at least one name pattern. All matching configurations and labels are discarded in the correct order with respect to potential dependencies. If one configuration or label could not be discarded because one of its dependencies would remain, nothing is discarded โ all or nothing, periodt. Each individual name pattern must match at least one named configuration or label.
๐ vcl.inline <configname> <quoted_VCLstring> [auto|cold|warm] ๐
Compile and load the VCL data under the name provided. Inline VCL, no file needed, we're flexible like that.
Multi-line VCL can be input using the here document ref_syntax. ๐
๐ vcl.label <label> <configname> ๐
Apply label to configuration. Name drop incoming.
A VCL label is like a UNIX symbolic link, a name without substance, which points to another VCL.
Labels are mandatory whenever one VCL references another. No label, no reference, no cap. ๐ซ
๐ธ vcl.list [-j] ๐ธ
List all loaded configuration. The roster.
Unless -j is specified for JSON output, the output format is five or seven columns of dynamic width, separated by white space, with the fields:
status:active,availableordiscardedstate:label,cold,warm, orautotemperature:init,cold,warm,busyorcoolingbusy: number of references to this vcl (integer)name: the name given to this vcl or label[ <- | -> ]and label info โ the last two fields)-> <vcl>: label "points to" the named<vcl><- (<n> label[s]): the vcl has<n>label(s)
๐ฆ vcl.load <configname> <filename> [auto|cold|warm] ๐ฆ
Compile and load the VCL file under the name provided. From disk to live, iconic behaviour.
โจ vcl.show [-v] [<configname>] โจ
Display the source code for the specified configuration. Reading the receipts.
๐ vcl.state <configname> auto|cold|warm ๐
Force the state of the named configuration. No waiting around for it to decide.
๐ฅ vcl.symtab ๐ฅ
Dump the VCL symbol-tables. All the lore, exposed.
โญ vcl.use <configname|label> โญ
Switch to the named configuration immediately. No soft launch, we're live right now. ๐
๐ง Backend Pattern ๐ง
A backend pattern can be a backend name or a combination of a VCL name and backend name in "VCL.backend" format. If the VCL name is omitted, the active VCL is assumed. Partial matching on the backend and VCL names is supported using shell-style wildcards, e.g. asterisk (*). Fuzzy matching but make it fashionable.
Examples:
backend.list def*
backend.list b*.def*
backend.set_health default sick
backend.set_health def* healthy
backend.set_health * auto
๐ Ban Expressions ๐
A ban expression consists of one or more conditions. A condition consists of a field, an operator, and an argument. Conditions can be ANDed together with "&&". Teamwork makes the dream work.
A field can be any of the variables from VCL, for instance req.url, req.http.host or obj.http.set-cookie.
Operators are "==" for direct comparison, "~" for a regular expression match, and ">" or "<" for size comparisons. Prepending an operator with "!" negates the expression. Not me negating my own ban.
The argument could be a quoted string, a regexp, or an integer. Integers can have "KB", "MB", "GB" or "TB" appended for size related fields. ๐
๐ VCL Temperature ๐
A VCL program goes through several states related to the different commands: it can be loaded, used, and later discarded. You can load several VCL programs and switch at any time from one to another. There is only one active VCL, but the previous active VCL will be maintained active until all its transactions are over. No abrupt endings, everyone gets to finish their sentence.
Over time, if you often refresh your VCL and keep the previous versions around, resource consumption will increase, you can't escape that. However, most of the time you want to pay the price only for the active VCL and keep older VCLs in case you'd need to rollback to a previous version. Emotional support VCLs.
The VCL temperature allows you to minimize the footprint of inactive VCLs. Once a VCL becomes cold, Varnish will release all the resources that can be be later reacquired. You can manually set the temperature of a VCL or let varnish automatically handle it. ๐ง
๐ EXAMPLES ๐
Load a multi-line VCL using shell-style here document:
vcl.inline example << EOF
vcl 4.0;
backend www {
.host = "127.0.0.1";
.port = "8080";
}
EOF
Ban all requests where req.url exactly matches the string /news:
ban req.url == "/news"
Ban all documents where the serving host is "example.com" or "www.example.com", and where the Set-Cookie header received from the backend contains "USERID=1663":
ban req.http.host ~ "^(?i)(www\.)?example\.com$" && obj.http.set-cookie ~ "USERID=1663"
๐ AUTHORS ๐
This manual page was originally written by Per Buer and later modified by Federico G. Schwindt, Dridi Boukelmoune, Lasse Karstensen and Poul-Henning Kamp. Legends, all of them. ๐
๐ SEE ALSO ๐
varnishadm(1)varnishd(1)vcl(7)- For API use of the CLI: The Reference Manual.
and that's the whole VARNISH-CLI(7) page, bestie โ go forth and be iconic with your CLI ๐ฆโจ๐
๐ฆ where this page comes from
- fedora 44: varnish 8.0.2-1.fc44 ยท BSD-2-Clause AND (BSD-2-Clause-FreeBSD AND BSD-3-Clause AND LicenseRef-Fedora-Public-Domain AND Zlib)
- fedora 44: varnish 8.0.2-1.fc44 ยท BSD-2-Clause AND (BSD-2-Clause-FreeBSD AND BSD-3-Clause AND LicenseRef-Fedora-Public-Domain AND Zlib)
- ๐ the page's license: BSD-2-Clause
- Copyright (c) 2011-2021 Varnish Software AS
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms