# The simple and easy way to embed static files into Go binaries.

### Related tags

Resource Embedding build packr gobuffalo
##### Overview

NOTICE: Please consider migrating your projects to github.com/markbates/pkger. It has an idiomatic API, minimal dependencies, a stronger test suite (tested directly against the std lib counterparts), transparent tooling, and more.

https://blog.gobuffalo.io/introducing-pkger-static-file-embedding-in-go-1ce76dc79c65

# packr (v1)

## Packr has been updated to v2! Please read the ./v2/README.md file for more details.

Packr is a simple solution for bundling static assets inside of Go binaries. Most importantly it does it in a way that is friendly to developers while they are developing.

## Intro Video

To get an idea of the what and why of packr, please enjoy this short video: https://vimeo.com/219863271.

## Installation

To install Packr utility

$go get -u github.com/gobuffalo/packr/packr  To get the dependency $ go get -u github.com/gobuffalo/packr


## Usage

### In Code

The first step in using Packr is to create a new box. A box represents a folder on disk. Once you have a box you can get string or []byte representations of the file.

// set up a new box by giving it a (relative) path to a folder on disk:
box := packr.NewBox("./templates")

// Get the string representation of a file, or an error if it doesn't exist:
html, err := box.FindString("index.html")

// Get the []byte representation of a file, or an error if it doesn't exist:
html, err := box.Find("index.html")

### What is a Box?

A box represents a folder, and any sub-folders, on disk that you want to have access to in your binary. When compiling a binary using the packr CLI the contents of the folder will be converted into Go files that can be compiled inside of a "standard" go binary. Inside of the compiled binary the files will be read from memory. When working locally the files will be read directly off of disk. This is a seamless switch that doesn't require any special attention on your part.

#### Example

├── main.go
└── templates
│   └── index.html
└── index.html


The following program will read the ./templates/admin/index.html file and print it out.

package main

import (
"fmt"

"github.com/gobuffalo/packr"
)

func main() {
box := packr.NewBox("./templates")

if err != nil {
log.Fatal(err)
}
fmt.Println(s)
}

In order to get static files into a Go binary, those files must first be converted to Go code. To do that, Packr, ships with a few tools to help build binaries. See below.

During development, however, it is painful to have to keep running a tool to compile those files.

Packr uses the following resolution rules when looking for a file:

1. Look for the file in-memory (inside a Go binary)
2. Look for the file on disk (during development)

Because Packr knows how to fall through to the file system, developers don't need to worry about constantly compiling their static files into a binary. They can work unimpeded.

Packr takes file resolution a step further. When declaring a new box you use a relative path, ./templates. When Packr receives this call it calculates out the absolute path to that directory. By doing this it means you can be guaranteed that Packr can find your files correctly, even if you're not running in the directory that the box was created in. This helps with the problem of testing, where Go changes the pwd for each package, making relative paths difficult to work with. This is not a problem when using Packr.

## Usage with HTTP

A box implements the http.FileSystem interface, meaning it can be used to serve static files.

package main

import (
"net/http"

"github.com/gobuffalo/packr"
)

func main() {
box := packr.NewBox("./templates")

http.Handle("/", http.FileServer(box))
http.ListenAndServe(":3000", nil)
}

## Building a Binary (the easy way)

When it comes time to build, or install, your Go binary, simply use packr build or packr install just as you would go build or go install. All flags for the go tool are supported and everything works the way you expect, the only difference is your static assets are now bundled in the generated binary. If you want more control over how this happens, looking at the following section on building binaries (the hard way).

## Building a Binary (the hard way)

Before you build your Go binary, run the packr command first. It will look for all the boxes in your code and then generate .go files that pack the static files into bytes that can be bundled into the Go binary.

$packr  Then run your go build command like normal. NOTE: It is not recommended to check-in these generated -packr.go files. They can be large, and can easily become out of date if not careful. It is recommended that you always run packr clean after running the packr tool. #### Cleaning Up When you're done it is recommended that you run the packr clean command. This will remove all of the generated files that Packr created for you. $ packr clean


Why do you want to do this? Packr first looks to the information stored in these generated files, if the information isn't there it looks to disk. This makes it easy to work with in development.

## Building/Moving a portable release

When it comes to building multiple releases you typically want that release to be built in a specific directory.

For example: ./releases

However, because passing a .go file requires absolute paths, we must compile the release in the appropriate absolute path.

GOOS=linux GOARCH=amd64 packr build

Now your project_name binary will be built at the root of your project dir. Great!

All that is left to do is to move that binary to your release dir:

Linux/macOS/Windows (bash)

mv ./project_name ./releases

Windows (cmd):

move ./project_name ./releases

Powershell:

Move-Item -Path .\project_name -Destination .\releases\

If you target for Windows when building don't forget that it's project_name.exe

Now you can make multiple releases and all of your needed static files will be available!

#### Summing it up:

Example Script for building to 3 common targets:

GOOS=darwin GOARCH=amd64 packr build && mv ./project_name ./releases/darwin-project_name \
&& GOOS=linux GOARCH=amd64 packr build && mv ./project_name ./releases/linux-project_name \
&& GOOS=windows GOARCH=386 packr build && mv ./project_name.exe ./releases/project_name.exe \
&& packr clean

## Debugging

The packr command passes all arguments down to the underlying go command, this includes the -v flag to print out go build information. Packr looks for the -v flag, and will turn on its own verbose logging. This is very useful for trying to understand what the packr command is doing when it is run.

• #### packr2 import issues with go modules

Hello and thank you for a great tool!

I've been converting my projects over to go modules and ran into an issue with a project that uses packr2.

The issue is that the main-packr.go file imports by path:

...
import _ "Users/cmorgan/projects/xxxx/packrd
...


If I rewrite this to use the module path from the first line of go.mod:

module github.com/user/package/subdirectory


like:

...
import _ "github.com/user/package/subdirectory/packrd"
...


Everything works as expected.

It looks like you can retrieve this module like:

$go list github.com/user/package/subdirectory  Thoughts on how best to support go modules with packr2? I'm ok with rewriting the main-packrd.go file but I'm guessing lots of people are going to start bumping into this issue once they switch to go modules (which btw have worked pretty well, I was skeptical at first). opened by chmorgan 31 • #### Calling packr build/install with a *.go files causes boxes not to be packed Hey so this is a longshot.. I am using packr to compile static assets to a single go binary. It's a webserver. I can move the exe around on my machine and it works. However when someone else on a different windows machine tries it, it says 404 not found :thinking_face: Haven't tried on Mac yet, but I guess I would run into the same issues :joy: Here is my repo: https://github.com/selfup/hmrcmd Any help would be awesome! 🙏 opened by selfup 20 • #### packr2 uses absolute paths packr2 creates main-packr.go with import _ "T:/absolute/path/to/project/directory/packrd"  rather than using a relative path like import _ "./packrd"  which of course doesn't work on Windows. After running packr2 I can of course manually edit main-packr.go to make it use the relative path, but after compiling, box.FindString seems like it tries to read the file on the disk itself? But errors when it can't find it. So if I run the program on my local machine, it works fine because it has access to T:\absolute\path\to\project\directory\templates, but it errors on remote machines: 2018/12/04 14:20:42 http: panic serving x.x.x.x:60036: FindFirstFile T:\absolute\path\to\project\directory\templates\base.html: The system cannot find the path specified. goroutine 32 [running]: net/http.(*conn).serve.func1(0xc00063b720) D:/dev/go/goroot/src/net/http/server.go:1746 +0xd7 panic(0x994a40, 0xc00005d440) D:/dev/go/goroot/src/runtime/panic.go:513 +0x1c7 ... net/http.HandlerFunc.ServeHTTP(0xa6e308, 0xaefb60, 0xc00062b420, 0xc000100200) D:/dev/go/goroot/src/net/http/server.go:1964 +0x4b net/http.(*ServeMux).ServeHTTP(0xf822a0, 0xaefb60, 0xc00062b420, 0xc000100200) D:/dev/go/goroot/src/net/http/server.go:2361 +0x12e net/http.serverHandler.ServeHTTP(0xc000492dd0, 0xaefb60, 0xc00062b420, 0xc000100200) D:/dev/go/goroot/src/net/http/server.go:2741 +0xb2 net/http.(*conn).serve(0xc00063b720, 0xaf0520, 0xc000040380) D:/dev/go/goroot/src/net/http/server.go:1847 +0x64d created by net/http.(*Server).Serve D:/dev/go/goroot/src/net/http/server.go:2851 +0x2fc  All of this works fine in packr but does not in packr2. opened by ajruckman 16 • #### Packr embed silently fails when project dir is a symlink Gitlab CI does not support custom checkout directories (like in$GOPATH), which meant my application directory was a symlink. Which seemed to work just fine, but the binary lacked the embedded files. For example:

$packr -i opencl$ ls opencl
opencl-packr.go
# all good
$go build$ ./myapp
# ok
$rm -rf opencl # let's try this again wiithout the files on disk$ ./myapp
panic: file does not exist


Real build log here: https://gitlab.com/blockforge/blockforge/-/jobs/50043767 (relevant portion at the bottom)

opened by jgillich 14
• #### Having invalid (but unused) go files anywhere in the project path fails packr build

Trying to use the packr build command in a project that has invalid (but unused) go files fails the command.

I'm using JetBrains File Templates to create some boilerplate code in my project. Those involve creating and storing invalid go files within my project structure (inside the .idea project directory).

Now, when I execute packr build in the project root I get the following output:

$packr build Error: /Users/fletcher/go/src/project/.idea/fileTemplates/file_template_1.go:1:1: illegal character U+0023 '#' Usage: packr build [flags] Flags: -h, --help help for build  Note: go build works just fine opened by ckaik 13 • #### Packer v2 http.FileServer(box) failed to serve index.html with go v1.12.4 and packr Version 2.2.0? Hello, index.html create a redirect loop then fail with url like "http://localhost:3000//" (All other static file work as expected); OS MacOs v10.14.4 Go version 1.12.4 Packr2 V2.2.0 test program : package main import ( "fmt" "net/http" packr "github.com/gobuffalo/packr/v2" ) func main() { box := packr.New("my template", "../mysite/templates") http.Handle("/", http.FileServer(box)) fmt.Println("listening on :3000") http.ListenAndServe(":3000", nil) }  help wanted opened by gpkfr 12 • #### packr not detecting files even though it is in the binary # Packr Test This repository was created to test out an error I got when using packr. ## Usage go get -d github.com/yadunut/packr-test/...  or git clone https://github.com/yadunut/packr-test  ## No Issues cd packr-test packr build cmd/server/main.go ./main  ### Expected Init Function 2 files in ./templates ListFiles function Files in box: index.tmpl register.tmpl  ### Actual Init Function 2 files in ./templates ListFiles function Files in box: index.tmpl register.tmpl  ## Issues Changed the path to the repository cd .. mv packr-test packr-tests cd packr-tests ./main cd .. mv packr-tests packr-test cd packr-test  ### Expected Init Function 2 files in ./templates ListFiles function Files in box: index.tmpl register.tmpl  ### Actual Init Function 0 files in ./templates ListFiles function Files in box: index.tmpl register.tmpl  ## What Happened? The init function doesn't detect files in the binary, but detects files when they're in the folders. Outside of the init function, there are no issues. opened by yadunut 12 • #### packr2 does not find boxes when package main is in subdirectory in modules setup Hi. Im using packr2 with app using modules. GO111MODULE=on is exported. The package main is in $PROJECT_ROOT/cmd/app

Executing packr2 ./cmd/app with verbose flag says it found 0 boxes. Even if path to files is absolute.

When I move package main to root of the project, all works as expected.

Though, I don't want to have package main in root of my project, as I have many binaries for it.

Any suggestions how to have packr2 working in such case?

opened by Jarema 11
• #### box.open open "/" return dir

now box.Open("/") is return a file (isDir is false) and err is nil
on http.serveFile the code in net/http/fs.go

	if redirect {
// redirect to canonical path: / at end of directory url
// r.URL.Path always begins with /
url := r.URL.Path
if d.IsDir() {
if url[len(url)-1] != '/' {
localRedirect(w, r, path.Base(url)+"/")
return
}
} else {
if url[len(url)-1] == '/' {
localRedirect(w, r, "../"+path.Base(url))
return
}
}
}

// redirect if the directory name doesn't end in a slash
if d.IsDir() {
url := r.URL.Path
if url[len(url)-1] != '/' {
localRedirect(w, r, path.Base(url)+"/")
return
}
}

// use contents of index.html for directory, if present
if d.IsDir() {
index := strings.TrimSuffix(name, "/") + indexPage
ff, err := fs.Open(index)
if err == nil {
defer ff.Close()
dd, err := ff.Stat()
if err == nil {
name = index
d = dd
f = ff
}
}
}
}


code is redirect to "/" not “/index.html"

i fix the code in func (b *Box) Open(name string) (http.File, error) is

        plog.Debug(b, "Open", "name", name)
if strings.EqualFold("/", name) {
return file.NewDir("/")
}
f, err := b.Resolve(name)
if err != nil {
if len(filepath.Ext(name)) == 0 {
return b.openWoExt(name)
}
return f, err
}
f, err = file.NewFileR(name, f)
plog.Debug(b, "Open", "name", f.Name(), "file", f.Name())
return f, err

opened by zcx2001 11
• #### Packr in a subdirectory of a module

I use go modules in a project and when trying to generate packr in a subpackage of module, I get the following generated file:

// +build !skippackr
// Code generated by github.com/gobuffalo/packr/v2. DO NOT EDIT.

// You can use the "packr clean" command to clean up this,
// and any other packr generated files.
package form

import _ "home/circleci/project/internal/cli/command/form/packrd"


(this is from circle)

The subpackage I executed packr2 in is internal/cli/command/form, and it's outside of the GOPATH. When executing packr2 with GO111MODULE=on it stops with an error:

Error: go.mod cannot be read or does not exist while go module is enabled.

Is it a bug or a limitation that packr2 can only be executed in the root module?

opened by sagikazarmark 11
• #### panic: runtime error: invalid memory address or nil pointer dereference

(GO noob here) I'm trying to follow some instructions to build a go project. (I'm running Ubuntu 17.10 , go 1.10) I set my GOPATH to a new workspace directory.
Then, I installed packr using the instructions found in this project:

go get -u github.com/gobuffalo/packr/...


And when I try to run packr I get a segmentation fault:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x8 pc=0x6df339]

goroutine 633 [running]:
github.com/gobuffalo/packr/builder.(*visitor).eval(0xc4206cb810, 0x81a600, 0xc4204ea090, 0x0, 0x0)
/.../gorkspace/src/github.com/gobuffalo/packr/builder/visitor.go:88 +0x69
github.com/gobuffalo/packr/builder.(*visitor).Visit(0xc4206cb810, 0x81a600, 0xc4204ea090, 0x818540, 0xc4206cb810)
/.../gorkspace/src/github.com/gobuffalo/packr/builder/visitor.go:69 +0x4c
go/ast.Walk(0x818540, 0xc4206cb810, 0x81a600, 0xc4204ea090)
/usr/local/go/src/go/ast/walk.go:52 +0x66
go/ast.walkDeclList(0x818540, 0xc4206cb810, 0xc420478600, 0xb, 0x10)
/usr/local/go/src/go/ast/walk.go:38 +0x81
go/ast.Walk(0x818540, 0xc4206cb810, 0x81a580, 0xc420607200)
/usr/local/go/src/go/ast/walk.go:353 +0x2650
github.com/gobuffalo/packr/builder.(*visitor).Run(0xc4206cb810, 0x9f86e8, 0x5a)
/.../gorkspace/src/github.com/gobuffalo/packr/builder/visitor.go:42 +0x1e0
github.com/gobuffalo/packr/builder.(*Builder).process(0xc4200aa460, 0xc42040d0e0, 0x5a, 0xc420034448, 0xc4203eaf90)
/.../gorkspace/src/github.com/gobuffalo/packr/builder/builder.go:90 +0x175
github.com/gobuffalo/packr/builder.(*Builder).Run.func1.1(0xc400000008, 0x7ed968)
/.../gorkspace/src/github.com/gobuffalo/packr/builder/builder.go:48 +0x3c
golang.org/x/sync/errgroup.(*Group).Go.func1(0xc420034440, 0xc4204021c0)
/.../gorkspace/src/golang.org/x/sync/errgroup/errgroup.go:58 +0x57
created by golang.org/x/sync/errgroup.(*Group).Go
/.../gorkspace/src/golang.org/x/sync/errgroup/errgroup.go:55 +0x66

opened by maasg 11

This PR allows binaries to be built for s390x. Just like ppc64le, s390x does not have Windows or Darwin support.

@markbates and @stanislas-m let me know if you have any questions!

opened by james-crowley 1
• #### packr2 does not respect go build's module path

I'm running into the following issue:

\$ packr2 build -v --tags "json1" -ldflags="-X 'main.Version=1.0.0.0-dev'" -o bin/flyd ./cmd/flyd
// tons of logs
// ...
DEBU[2021-07-12T11:09:17-04:00] go build -v --tags json1 -ldflags=-X 'main.Version=1.0.0.0-dev' -o bin/flyd flyd
package flyd is not in GOROOT (/usr/lib/go/src/flyd)
Error: exit status 1


Note the path (./cmd/flyd) I'm trying to build is changed in the go build invocation from packr2.

Edit: my current workaround is to go build with the same arguments, but the correct path, right after this, ignoring the error.

opened by jeromegn 0
• #### Version upgrade due to vulnerabilities

Hello in order to correct the vulnerabilities as described in #290, I suggest you this version upgrade. However, before tagging a version of packr (v1), you will need to tag a version of packr v2 and reference this latest version in packr v1 thank you !

opened by DonRenando 0
• #### Vulnerability due to usage of github.com/coreos:etcd:3.3.10

Hello !

A high severity vulnerability has been discovered due to the use of github.com/coreos:etcd:3.3.10

Vulnerability description: etcd before versions 3.3.23 and 3.4.10 does not perform any password length validation, which allows for very short passwords, such as those with a length of one. This may allow an attacker to guess or brute-force users' passwords with little computational effort.

Occurrences

github.com/coreos:etcd:3.3.10 is a transitive dependency introduced by the following direct dependency(s):

• github.com/gobuffalo/packr └─ github.com/spf13:cobra:0.0.5 └─ github.com/spf13:viper:1.3.2 └─ github.com/coreos:etcd:3.3.10 and

• github.com/gobuffalo/packr └─ github.com/gobuffalo/packr/[email protected] └─ github.com/spf13:cobra:0.0.5 └─ github.com/spf13:viper:1.3.2 └─ github.com/coreos:etcd:3.3.10

currently there are 3 CVE at this version (3.3.10) : [CVE-2020-15114] [CVE-2020-15136] [CVE-2020-15115]

Move to the latest version of spf13:cobra v1.2.1 will be able to resolve these vulnerabilities as well as several others of the intermediate versions.

opened by DonRenando 0
• #### Packr2 is running normally, but uses in the GitHub Action environment, the following error occurs:

the following error occurs

main-packr.go:8:8: package home/runner/work/KnowlGraph/KnowlGraph/packrd is not in GOROOT (/opt/hostedtoolcache/go/1.15.12/x64/src/home/runner/work/KnowlGraph/KnowlGraph/packrd)

opened by excing 2
##### Releases(v2.8.3)
###### Generates go code to embed resource files into your library or executable

Deprecating Notice go is now going to officially support embedding files. The go command will support //go:embed tags. Go Embed Generates go code to e

6.3k Jun 2, 2021
###### Embed files into a Go executable

statik statik allows you to embed a directory of static files into your Go binary to be later served from an http.FileSystem. Is this a crazy idea? No

3.5k Dec 8, 2022
###### A tool to be used with 'go generate' to embed external template files into Go code.

templify A tool to be used with 'go generate' to embed external template files into Go code. Scenario An often used scenario in developing go applicat

28 Sep 27, 2022
###### a better customizable tool to embed files in go; also update embedded files remotely without restarting the server

fileb0x What is fileb0x? A better customizable tool to embed files in go. It is an alternative to go-bindata that have better features and organized c

620 Nov 30, 2022
###### :file_folder: Embeds static resources into go files for single binary compilation + works with http.FileSystem + symlinks

Package statics Package statics embeds static files into your go applications. It provides helper methods and objects to retrieve embeded files and se

65 Sep 27, 2022
###### go.rice is a Go package that makes working with resources such as html,js,css,images,templates, etc very easy.

go.rice go.rice is a Go package that makes working with resources such as html,js,css,images and templates easy. During development go.rice will load

2.3k Nov 24, 2022
###### A simple file embedder for Go

esc esc embeds files into go programs and provides http.FileSystem interfaces to them. It adds all named files or files recursively under named direct

630 Dec 1, 2022
###### Takes an input http.FileSystem (likely at go generate time) and generates Go code that statically implements it.

vfsgen Package vfsgen takes an http.FileSystem (likely at go generate time) and generates Go code that statically implements the provided http.FileSys

951 Dec 8, 2022
###### Embed static files in Go binaries (replacement for gobuffalo/packr)

Pkger github.com/markbates/pkger is a tool for embedding static files into Go binaries. It will, hopefully, be a replacement for github.com/gobuffalo/

1.2k Dec 5, 2022
###### Get an embed.FS from inside an embed.FS

embed.FS wrapper providing additional functionality Features Get an embed.FS from an embedded subdirectory Handy Copy(sourcePath, targetPath) method t

22 Sep 27, 2022
###### Using brotli compression to embed static files in Go.

?? Broccoli go get -u aletheia.icu/broccoli Broccoli uses brotli compression to embed a virtual file system of static files inside Go executables. A f

527 Nov 25, 2022
###### Split multiple Kubernetes files into smaller files with ease. Split multi-YAML files into individual files.

Split multiple Kubernetes files into smaller files with ease. Split multi-YAML files into individual files.

199 Nov 28, 2022
###### Split multiple Kubernetes files into smaller files with ease. Split multi-YAML files into individual files.

kubectl-slice: split Kubernetes YAMLs into files kubectl-slice is a neat tool that allows you to split a single multi-YAML Kubernetes manifest into mu

200 Dec 2, 2022
###### Use this program to embed sh scripts in binaries

sh2bin Use this program to embed sh scripts in binaries. Feel free to fork this

17 Nov 9, 2022
###### Generates go code to embed resource files into your library or executable

Deprecating Notice go is now going to officially support embedding files. The go command will support //go:embed tags. Go Embed Generates go code to e

6.3k Jun 2, 2021
###### Embed files into a Go executable

statik statik allows you to embed a directory of static files into your Go binary to be later served from an http.FileSystem. Is this a crazy idea? No

3.5k Dec 8, 2022
###### A tool to be used with 'go generate' to embed external template files into Go code.

templify A tool to be used with 'go generate' to embed external template files into Go code. Scenario An often used scenario in developing go applicat

28 Sep 27, 2022
###### Embed files into a Go executable

statik statik allows you to embed a directory of static files into your Go binary to be later served from an http.FileSystem. Is this a crazy idea? No

3.5k Dec 1, 2022
###### a better customizable tool to embed files in go; also update embedded files remotely without restarting the server

fileb0x What is fileb0x? A better customizable tool to embed files in go. It is an alternative to go-bindata that have better features and organized c

620 Nov 30, 2022