diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 76657147e..0706252d9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -155,6 +155,7 @@ Add your fs to the docs * `README.md` - main Github page * `docs/content/remote.md` - main docs page * `docs/content/overview.md` - overview docs + * `docs/content/docs.md` - list of remotes in config section * `docs/content/about.md` - front page of rclone.org * `docs/layouts/chrome/navbar.html` - add it to the website navigation * `make_manual.py` - add the page to the `docs` constant diff --git a/amazonclouddrive/amazonclouddrive.go b/amazonclouddrive/amazonclouddrive.go index 9bfda9b0a..78f048b3b 100644 --- a/amazonclouddrive/amazonclouddrive.go +++ b/amazonclouddrive/amazonclouddrive.go @@ -69,10 +69,10 @@ func init() { } }, Options: []fs.Option{{ - Name: oauthutil.ConfigClientID, + Name: fs.ConfigClientID, Help: "Amazon Application Client Id - leave blank normally.", }, { - Name: oauthutil.ConfigClientSecret, + Name: fs.ConfigClientSecret, Help: "Amazon Application Client Secret - leave blank normally.", }}, }) diff --git a/docs/content/amazonclouddrive.md b/docs/content/amazonclouddrive.md index d74df1686..ba74d4a99 100644 --- a/docs/content/amazonclouddrive.md +++ b/docs/content/amazonclouddrive.md @@ -58,6 +58,9 @@ d) Delete this remote y/e/d> y ``` +See the [remote setup docs](/remote_setup/) for how to set it up on a +machine with no Internet browser available. + Note that rclone runs a webserver on your local machine to collect the token as returned from Amazon. This only runs from the moment it opens your browser to the moment you get back the verification diff --git a/docs/content/docs.md b/docs/content/docs.md index 363fc4473..5b6591d4a 100644 --- a/docs/content/docs.md +++ b/docs/content/docs.md @@ -25,6 +25,11 @@ See the following for detailed instructions for * [Dropbox](/dropbox/) * [Google Cloud Storage](/googlecloudstorage/) * [Local filesystem](/local/) + * [Amazon Cloud Drive](/amazonclouddrive/) + * [Backblaze B2](/b2/) + * [Hubic](/hubic/) + * [Microsoft One Drive](/onedrive/) + * [Yandex Disk](/yandex/) Usage ----- diff --git a/docs/content/faq.md b/docs/content/faq.md index 7bccce4d8..428ceccb1 100644 --- a/docs/content/faq.md +++ b/docs/content/faq.md @@ -12,31 +12,17 @@ Frequently Asked Questions Yes they do. All the rclone commands (eg `sync`, `copy` etc) will work on all the remote storage systems. - ### Can I copy the config from one machine to another ### Sure! Rclone stores all of its config in a single file. If you want to find this file, the simplest way is to run `rclone -h` and look at -the help for the `--config` flag which will tell you where it is. Eg, +the help for the `--config` flag which will tell you where it is. -``` -$ rclone -h -Sync files and directories to and from local and remote object stores - v1.18. -[snip] -Options: - --bwlimit=0: Bandwidth limit in kBytes/s, or use suffix k|M|G - --checkers=8: Number of checkers to run in parallel. - -c, --checksum=false: Skip based on checksum & size, not mod-time & size - --config="/home/user/.rclone.conf": Config file. -[snip] -``` +See the [remote setup docs](/remote_setup/) for more info. -So in this config the config file can be found in -`/home/user/.rclone.conf`. - -Just copy that to the equivalent place in the destination (run `rclone --h` above again on the destination machine if not sure). +### How do I configure rclone on a remote / headless box with no browser? ### +This has now been documented in its own [remote setup page](/remote_setup/). ### Can rclone sync directly from drive to s3 ### diff --git a/docs/content/hubic.md b/docs/content/hubic.md index 3595069ef..a1b1471da 100644 --- a/docs/content/hubic.md +++ b/docs/content/hubic.md @@ -60,6 +60,9 @@ d) Delete this remote y/e/d> y ``` +See the [remote setup docs](/remote_setup/) for how to set it up on a +machine with no Internet browser available. + Note that rclone runs a webserver on your local machine to collect the token as returned from Hubic. This only runs from the moment it opens your browser to the moment you get back the verification code. This diff --git a/docs/content/onedrive.md b/docs/content/onedrive.md index c0d41790e..4e3dc0de9 100644 --- a/docs/content/onedrive.md +++ b/docs/content/onedrive.md @@ -59,6 +59,9 @@ d) Delete this remote y/e/d> y ``` +See the [remote setup docs](/remote_setup/) for how to set it up on a +machine with no Internet browser available. + Note that rclone runs a webserver on your local machine to collect the token as returned from Microsoft. This only runs from the moment it opens your browser to the moment you get back the verification diff --git a/docs/content/remote_setup.md b/docs/content/remote_setup.md new file mode 100644 index 000000000..67de10845 --- /dev/null +++ b/docs/content/remote_setup.md @@ -0,0 +1,88 @@ +--- +title: "Remote Setup" +description: "Configuring rclone up on a remote / headless machine" +date: "2016-01-07" +--- + +# Configuring rclone on a remote / headless machine # + +Some of the configurations (those involving oauth2) require an +Internet connected web browser. + +If you are trying to set rclone up on a remote or headless box with no +browser available on it (eg a NAS or a server in a datacenter) then +you will need to use an alternative means of configuration. There are +two ways of doing it, described below. + +## Configuring using rclone authorize ## + +On the headless box + +``` +... +Remote config +Use auto config? + * Say Y if not sure + * Say N if you are working on a remote or headless machine +y) Yes +n) No +y/n> n +For this to work, you will need rclone available on a machine that has a web browser available. +Execute the following on your machine: + rclone authorize "amazon cloud drive" +Then paste the result below: +result> +``` + +Then on your main desktop machine + +``` +rclone authorize "amazon cloud drive" +If your browser doesn't open automatically go to the following link: http://127.0.0.1:53682/auth +Log in and authorize rclone for access +Waiting for code... +Got code +Paste the following into your remote machine ---> +SECRET_TOKEN +<---End paste +``` + +Then back to the headless box, paste in the code + +``` +result> SECRET_TOKEN +-------------------- +[acd12] +client_id = +client_secret = +token = SECRET_TOKEN +-------------------- +y) Yes this is OK +e) Edit this remote +d) Delete this remote +y/e/d> +``` + +## Configuring by copying the config file ## + +Rclone stores all of its config in a single configuration file. This +can easily be copied to configure a remote rclone. + +So first configure rclone on your desktop machine + + rclone config + +to set up the config file. + +Find the config file by running `rclone -h` and looking for the help for the `--config` option + +``` +$ rclone -h +[snip] + --config="/home/user/.rclone.conf": Config file. +[snip] +``` + +Now transfer it to the remote box (scp, cut paste, ftp, sftp etc) and +place it in the correct place (use `rclone -h` on the remote box to +find out where). diff --git a/docs/content/yandex.md b/docs/content/yandex.md index a5052780b..33719d279 100644 --- a/docs/content/yandex.md +++ b/docs/content/yandex.md @@ -58,7 +58,16 @@ d) Delete this remote y/e/d> y ``` -This remote is called `remote` and can now be used like this +See the [remote setup docs](/remote_setup/) for how to set it up on a +machine with no Internet browser available. + +Note that rclone runs a webserver on your local machine to collect the +token as returned from Yandex Disk. This only runs from the moment it +opens your browser to the moment you get back the verification code. +This is on `http://127.0.0.1:53682/` and this it may require you to +unblock it temporarily if you are running a host firewall. + +Once configured you can then use `rclone` like this, See top level directories diff --git a/drive/drive.go b/drive/drive.go index 7cbc58555..155a67b37 100644 --- a/drive/drive.go +++ b/drive/drive.go @@ -72,10 +72,10 @@ func init() { } }, Options: []fs.Option{{ - Name: oauthutil.ConfigClientID, + Name: fs.ConfigClientID, Help: "Google Application Client Id - leave blank normally.", }, { - Name: oauthutil.ConfigClientSecret, + Name: fs.ConfigClientSecret, Help: "Google Application Client Secret - leave blank normally.", }}, }) diff --git a/fs/config.go b/fs/config.go index b1714872a..155f310e5 100644 --- a/fs/config.go +++ b/fs/config.go @@ -26,6 +26,18 @@ import ( const ( configFileName = ".rclone.conf" + + // ConfigToken is the key used to store the token under + ConfigToken = "token" + + // ConfigClientID is the config key used to store the client id + ConfigClientID = "client_id" + + // ConfigClientSecret is the config key used to store the client secret + ConfigClientSecret = "client_secret" + + // ConfigAutomatic indicates that we want non-interactive configuration + ConfigAutomatic = "config_automatic" ) // SizeSuffix is parsed by flag with k/M/G suffixes @@ -533,21 +545,13 @@ func EditConfig() { } } -// Duplicated from oauthutil to avoid circular reference. -const ( - // ConfigClientID is the config key used to store the client id - ConfigClientID = "client_id" - - // ConfigClientSecret is the config key used to store the client secret - ConfigClientSecret = "client_secret" - - // ConfigAutomatic indicates that we want non-interactive configuration - ConfigAutomatic = "config_automatic" -) - // Authorize is for remote authorization of headless machines. -func Authorize() { - args := pflag.Args()[1:] +// +// It expects 1 or 3 arguments +// +// rclone authorize "fs name" +// rclone authorize "fs name" "client id" "client secret" +func Authorize(args []string) { switch len(args) { case 1, 3: default: @@ -560,7 +564,7 @@ func Authorize() { } if fs.Config == nil { - log.Fatalf("No configuration on fs %v", newType) + log.Fatalf("Can't authorize fs %q", newType) } // Name used for temporary fs name := "**temp-fs**" diff --git a/googlecloudstorage/googlecloudstorage.go b/googlecloudstorage/googlecloudstorage.go index ceb139a5a..84514c8a1 100644 --- a/googlecloudstorage/googlecloudstorage.go +++ b/googlecloudstorage/googlecloudstorage.go @@ -65,10 +65,10 @@ func init() { } }, Options: []fs.Option{{ - Name: oauthutil.ConfigClientID, + Name: fs.ConfigClientID, Help: "Google Application Client Id - leave blank normally.", }, { - Name: oauthutil.ConfigClientSecret, + Name: fs.ConfigClientSecret, Help: "Google Application Client Secret - leave blank normally.", }, { Name: "project_number", diff --git a/hubic/hubic.go b/hubic/hubic.go index 7f3d716a8..379a6a425 100644 --- a/hubic/hubic.go +++ b/hubic/hubic.go @@ -54,10 +54,10 @@ func init() { } }, Options: []fs.Option{{ - Name: oauthutil.ConfigClientID, + Name: fs.ConfigClientID, Help: "Hubic Client Id - leave blank normally.", }, { - Name: oauthutil.ConfigClientSecret, + Name: fs.ConfigClientSecret, Help: "Hubic Client Secret - leave blank normally.", }}, }) diff --git a/make_manual.py b/make_manual.py index ecb651555..04be1e686 100755 --- a/make_manual.py +++ b/make_manual.py @@ -16,6 +16,7 @@ docs = [ "about.md", "install.md", "docs.md", + "remote_setup.md", "filtering.md", "overview.md", "drive.md", diff --git a/oauthutil/oauthutil.go b/oauthutil/oauthutil.go index 1d1d212cf..3962af81b 100644 --- a/oauthutil/oauthutil.go +++ b/oauthutil/oauthutil.go @@ -17,18 +17,6 @@ import ( ) const ( - // ConfigToken is the key used to store the token under - ConfigToken = "token" - - // ConfigClientID is the config key used to store the client id - ConfigClientID = "client_id" - - // ConfigClientSecret is the config key used to store the client secret - ConfigClientSecret = "client_secret" - - // ConfigAutomatic indicates that we want non-interactive configuration - ConfigAutomatic = "config_automatic" - // TitleBarRedirectURL is the OAuth2 redirect URL to use when the authorization // code should be returned in the title bar of the browser, with the page text // prompting the user to copy the code and paste it in the application. @@ -64,7 +52,7 @@ type oldToken struct { // getToken returns the token saved in the config file under // section name. func getToken(name string) (*oauth2.Token, error) { - tokenString, err := fs.ConfigFile.GetValue(string(name), ConfigToken) + tokenString, err := fs.ConfigFile.GetValue(string(name), fs.ConfigToken) if err != nil { return nil, err } @@ -107,9 +95,9 @@ func putToken(name string, token *oauth2.Token) error { return err } tokenString := string(tokenBytes) - old := fs.ConfigFile.MustValue(name, ConfigToken) + old := fs.ConfigFile.MustValue(name, fs.ConfigToken) if tokenString != old { - fs.ConfigFile.SetValue(name, ConfigToken, tokenString) + fs.ConfigFile.SetValue(name, fs.ConfigToken, tokenString) fs.SaveConfig() fs.Debug(name, "Saving new token in config file") } @@ -155,12 +143,12 @@ func Context() context.Context { // If any value is overridden, true is returned. func overrideCredentials(name string, config *oauth2.Config) bool { changed := false - ClientID := fs.ConfigFile.MustValue(name, ConfigClientID) + ClientID := fs.ConfigFile.MustValue(name, fs.ConfigClientID) if ClientID != "" { config.ClientID = ClientID changed = true } - ClientSecret := fs.ConfigFile.MustValue(name, ConfigClientSecret) + ClientSecret := fs.ConfigFile.MustValue(name, fs.ConfigClientSecret) if ClientSecret != "" { config.ClientSecret = ClientSecret changed = true @@ -196,7 +184,7 @@ func NewClient(name string, config *oauth2.Config) (*http.Client, error) { // It may run an internal webserver to receive the results func Config(id, name string, config *oauth2.Config) error { changed := overrideCredentials(name, config) - automatic := fs.ConfigFile.MustValue(name, ConfigAutomatic) != "" + automatic := fs.ConfigFile.MustValue(name, fs.ConfigAutomatic) != "" // See if already have a token tokenString := fs.ConfigFile.MustValue(name, "token") diff --git a/onedrive/onedrive.go b/onedrive/onedrive.go index 615b4d1ee..c2fe62aae 100644 --- a/onedrive/onedrive.go +++ b/onedrive/onedrive.go @@ -65,10 +65,10 @@ func init() { } }, Options: []fs.Option{{ - Name: oauthutil.ConfigClientID, + Name: fs.ConfigClientID, Help: "Microsoft App Client Id - leave blank normally.", }, { - Name: oauthutil.ConfigClientSecret, + Name: fs.ConfigClientSecret, Help: "Microsoft App Client Secret - leave blank normally.", }}, }) diff --git a/rclone.go b/rclone.go index 3120c67d9..81381a219 100644 --- a/rclone.go +++ b/rclone.go @@ -227,9 +227,11 @@ var Commands = []Command{ { Name: "authorize", Help: ` - Remote authorization.`, + Remote authorization. Used to authorize a remote or headless + rclone from a machine with a browser - use as instructed by + rclone config.`, Run: func(fdst, fsrc fs.Fs) error { - fs.Authorize() + fs.Authorize(pflag.Args()[1:]) return nil }, NoStats: true, diff --git a/yandex/yandex.go b/yandex/yandex.go index 6f55397be..a1782a228 100644 --- a/yandex/yandex.go +++ b/yandex/yandex.go @@ -51,10 +51,10 @@ func init() { } }, Options: []fs.Option{{ - Name: oauthutil.ConfigClientID, + Name: fs.ConfigClientID, Help: "Yandex Client Id - leave blank normally.", }, { - Name: oauthutil.ConfigClientSecret, + Name: fs.ConfigClientSecret, Help: "Yandex Client Secret - leave blank normally.", }}, })